home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-07-28 | 114.9 KB | 4,001 lines | [TEXT/ttxt] |
- (*$c+,t-,d-,l-*)
- (***********************************************
- * *
- * Portable Pascal compiler *
- * ************************ *
- * *
- * Pascal P4 *
- * *
- * Authors: *
- * Urs Ammann *
- * Kesav Nori *
- * Christian Jacobi *
- * Address: *
- * Institut Fuer Informatik *
- * Eidg. Technische Hochschule *
- * CH-8096 Zuerich *
- * *
- * This code is fully documented in the book *
- * "Pascal Implementation" *
- * by Steven Pemberton and Martin Daniels *
- * published by Ellis Horwood, Chichester, UK *
- * ISBN: 0-13-653-0311 *
- * (also available in Japanese) *
- * *
- * Steven Pemberton, CWI/AA, *
- * Kruislaan 413, 1098 SJ Amsterdam, NL *
- * Steven.Pemberton@cwi.nl *
- * *
- ***********************************************)
-
- program pascalcompiler(input,output,prr);
-
- const displimit = 20; maxlevel = 10;
- intsize = 1;
- intal = 1;
- realsize = 1;
- realal = 1;
- charsize = 1;
- charal = 1;
- charmax = 1;
- boolsize = 1;
- boolal = 1;
- ptrsize = 1;
- adral = 1;
- setsize = 1;
- setal = 1;
- stackal = 1;
- stackelsize = 1;
- strglgth = 16;
- sethigh = 47;
- setlow = 0;
- ordmaxchar = 63;
- ordminchar = 0;
- maxint = 32767;
- lcaftermarkstack = 5;
- fileal = charal;
- (* stackelsize = minimum size for 1 stackelement
- = k*stackal
- stackal = scm(all other al-constants)
- charmax = scm(charsize,charal)
- scm = smallest common multiple
- lcaftermarkstack >= 4*ptrsize+max(x-size)
- = k1*stackelsize *)
- maxstack = 1;
- parmal = stackal;
- parmsize = stackelsize;
- recal = stackal;
- filebuffer = 4;
- maxaddr = maxint;
-
-
-
- type (*describing:*)
- (*************)
-
- marktype= ^integer;
- (*basic symbols*)
- (***************)
-
- symbol = (ident,intconst,realconst,stringconst,notsy,mulop,addop,relop,
- lparent,rparent,lbrack,rbrack,comma,semicolon,period,arrow,
- colon,becomes,labelsy,constsy,typesy,varsy,funcsy,progsy,
- procsy,setsy,packedsy,arraysy,recordsy,filesy,forwardsy,
- beginsy,ifsy,casesy,repeatsy,whilesy,forsy,withsy,
- gotosy,endsy,elsesy,untilsy,ofsy,dosy,tosy,downtosy,
- thensy,othersy);
- operator = (mul,rdiv,andop,idiv,imod,plus,minus,orop,ltop,leop,geop,gtop,
- neop,eqop,inop,noop);
- setofsys = set of symbol;
- chtp = (letter,number,special,illegal,
- chstrquo,chcolon,chperiod,chlt,chgt,chlparen,chspace);
-
- (*constants*)
- (***********)
- setty = set of setlow..sethigh;
- cstclass = (reel,pset,strg);
- csp = ^ constant;
- constant = record case cclass: cstclass of
- reel: (rval: packed array [1..strglgth] of char);
- pset: (pval: setty);
- strg: (slgth: 0..strglgth;
- sval: packed array [1..strglgth] of char)
- end;
-
- valu = record case intval: boolean of (*intval never set nor tested*)
- true: (ival: integer);
- false: (valp: csp)
- end;
-
- (*data structures*)
- (*****************)
- levrange = 0..maxlevel; addrrange = 0..maxaddr;
- structform = (scalar,subrange,pointer,power,arrays,records,files,
- tagfld,variant);
- declkind = (standard,declared);
- stp = ^ structure; ctp = ^ identifier;
-
- structure = packed record
- marked: boolean; (*for test phase only*)
- size: addrrange;
- case form: structform of
- scalar: (case scalkind: declkind of
- declared: (fconst: ctp); standard: ());
- subrange: (rangetype: stp; min,max: valu);
- pointer: (eltype: stp);
- power: (elset: stp);
- arrays: (aeltype,inxtype: stp);
- records: (fstfld: ctp; recvar: stp);
- files: (filtype: stp);
- tagfld: (tagfieldp: ctp; fstvar: stp);
- variant: (nxtvar,subvar: stp; varval: valu)
- end;
-
- (*names*)
- (*******)
-
- idclass = (types,konst,vars,field,proc,func);
- setofids = set of idclass;
- idkind = (actual,formal);
- alpha = packed array [1..8] of char;
-
- identifier = packed record
- name: alpha; llink, rlink: ctp;
- idtype: stp; next: ctp;
- case klass: idclass of
- types: ();
- konst: (values: valu);
- vars: (vkind: idkind; vlev: levrange; vaddr: addrrange);
- field: (fldaddr: addrrange);
- proc, func: (case pfdeckind: declkind of
- standard: (key: 1..15);
- declared: (pflev: levrange; pfname: integer;
- case pfkind: idkind of
- actual: (forwdecl, externl: boolean);
- formal: ()))
- end;
-
-
- disprange = 0..displimit;
- where = (blck,crec,vrec,rec);
-
- (*expressions*)
- (*************)
- attrkind = (cst,varbl,expr);
- vaccess = (drct,indrct,inxd);
-
- attr = record typtr: stp;
- case kind: attrkind of
- cst: (cval: valu);
- varbl: (case access: vaccess of
- drct: (vlevel: levrange; dplmt: addrrange);
- indrct: (idplmt: addrrange))
- end;
-
- testp = ^ testpointer;
- testpointer = packed record
- elt1,elt2 : stp;
- lasttestp : testp
- end;
-
- (*labels*)
- (********)
- lbp = ^ labl;
- labl = record nextlab: lbp; defined: boolean;
- labval, labname: integer
- end;
-
- extfilep = ^filerec;
- filerec = record filename:alpha; nextfile:extfilep end;
-
- (*-------------------------------------------------------------------------*)
-
- var
- prr: text; (* comment this out when compiling with pcom *)
- (*returned by source program scanner
- insymbol:
- **********)
-
- sy: symbol; (*last symbol*)
- op: operator; (*classification of last symbol*)
- val: valu; (*value of last constant*)
- lgth: integer; (*length of last string constant*)
- id: alpha; (*last identifier (possibly truncated)*)
- kk: 1..8; (*nr of chars in last identifier*)
- ch: char; (*last character*)
- eol: boolean; (*end of line flag*)
-
-
- (*counters:*)
- (***********)
-
- chcnt: integer; (*character counter*)
- lc,ic: addrrange; (*data location and instruction counter*)
- linecount: integer;
-
-
- (*switches:*)
- (***********)
-
- dp, (*declaration part*)
- prterr, (*to allow forward references in pointer type
- declaration by suppressing error message*)
- list,prcode,prtables: boolean; (*output options for
- -- source program listing
- -- printing symbolic code
- -- displaying ident and struct tables
- --> procedure option*)
- debug: boolean;
-
-
- (*pointers:*)
- (***********)
- parmptr,
- intptr,realptr,charptr,
- boolptr,nilptr,textptr: stp; (*pointers to entries of standard ids*)
- utypptr,ucstptr,uvarptr,
- ufldptr,uprcptr,ufctptr, (*pointers to entries for undeclared ids*)
- fwptr: ctp; (*head of chain of forw decl type ids*)
- fextfilep: extfilep; (*head of chain of external files*)
- globtestp: testp; (*last testpointer*)
-
-
- (*bookkeeping of declaration levels:*)
- (************************************)
-
- level: levrange; (*current static level*)
- disx, (*level of last id searched by searchid*)
- top: disprange; (*top of display*)
-
- display: (*where: means:*)
- array [disprange] of
- packed record (*=blck: id is variable id*)
- fname: ctp; flabel: lbp; (*=crec: id is field id in record with*)
- case occur: where of (* constant address*)
- crec: (clev: levrange; (*=vrec: id is field id in record with*)
- cdspl: addrrange);(* variable address*)
- vrec: (vdspl: addrrange)
- end; (* --> procedure withstatement*)
-
-
- (*error messages:*)
- (*****************)
-
- errinx: 0..10; (*nr of errors in current source line*)
- errlist:
- array [1..10] of
- packed record pos: integer;
- nmr: 1..400
- end;
-
-
-
- (*expression compilation:*)
- (*************************)
-
- gattr: attr; (*describes the expr currently compiled*)
-
-
- (*structured constants:*)
- (***********************)
-
- constbegsys,simptypebegsys,typebegsys,blockbegsys,selectsys,facbegsys,
- statbegsys,typedels: setofsys;
- chartp : array[char] of chtp;
- rw: array [1..35(*nr. of res. words*)] of alpha;
- frw: array [1..9] of 1..36(*nr. of res. words + 1*);
- rsy: array [1..35(*nr. of res. words*)] of symbol;
- ssy: array [char] of symbol;
- rop: array [1..35(*nr. of res. words*)] of operator;
- sop: array [char] of operator;
- na: array [1..35] of alpha;
- mn: array [0..60] of packed array [1..4] of char;
- sna: array [1..23] of packed array [1..4] of char;
- cdx: array [0..60] of -4..+4;
- pdx: array [1..23] of -7..+7;
- ordint: array [char] of integer;
-
- intlabel,mxint10,digmax: integer;
- (*-------------------------------------------------------------------------*)
- procedure mark(var p: marktype); begin end;
- procedure release(p: marktype); begin end;
-
- procedure endofline;
- var lastpos,freepos,currpos,currnmr,f,k: integer;
- begin
- if errinx > 0 then (*output error messages*)
- begin write(output,linecount:6,' **** ':9);
- lastpos := 0; freepos := 1;
- for k := 1 to errinx do
- begin
- with errlist[k] do
- begin currpos := pos; currnmr := nmr end;
- if currpos = lastpos then write(output,',')
- else
- begin
- while freepos < currpos do
- begin write(output,' '); freepos := freepos + 1 end;
- write(output,'^');
- lastpos := currpos
- end;
- if currnmr < 10 then f := 1
- else if currnmr < 100 then f := 2
- else f := 3;
- write(output,currnmr:f);
- freepos := freepos + f + 1
- end;
- writeln(output); errinx := 0
- end;
- linecount := linecount + 1;
- if list and (not eof(input)) then
- begin write(output,linecount:6,' ':2);
- if dp then write(output,lc:7) else write(output,ic:7);
- write(output,' ')
- end;
- chcnt := 0
- end (*endofline*) ;
-
- procedure error(ferrnr: integer);
- begin
- if errinx >= 9 then
- begin errlist[10].nmr := 255; errinx := 10 end
- else
- begin errinx := errinx + 1;
- errlist[errinx].nmr := ferrnr
- end;
- errlist[errinx].pos := chcnt
- end (*error*) ;
-
- procedure insymbol;
- (*read next basic symbol of source program and return its
- description in the global variables sy, op, id, val and lgth*)
- label 1,2,3;
- var i,k: integer;
- digit: packed array [1..strglgth] of char;
- string: packed array [1..strglgth] of char;
- lvp: csp; test: boolean;
-
- procedure nextch;
- begin if eol then
- begin if list then writeln(output); endofline
- end;
- if not eof(input) then
- begin eol := eoln(input); read(input,ch);
- if list then write(output,ch);
- chcnt := chcnt + 1
- end
- else
- begin writeln(output,' *** eof ','encountered');
- test := false
- end
- end;
-
- procedure options;
- begin
- repeat nextch;
- if ch <> '*' then
- begin
- if ch = 't' then
- begin nextch; prtables := ch = '+' end
- else
- if ch = 'l' then
- begin nextch; list := ch = '+';
- if not list then writeln(output)
- end
- else
- if ch = 'd' then
- begin nextch; debug := ch = '+' end
- else
- if ch = 'c' then
- begin nextch; prcode := ch = '+' end;
- nextch
- end
- until ch <> ','
- end (*options*) ;
-
- begin (*insymbol*)
- 1:
- repeat while ((ch = ' ') or (ch = ' ')) and not eol do nextch;
- test := eol;
- if test then nextch
- until not test;
- if chartp[ch] = illegal then
- begin sy := othersy; op := noop;
- error(399); nextch
- end
- else
- case chartp[ch] of
- letter:
- begin k := 0;
- repeat
- if k < 8 then
- begin k := k + 1; id[k] := ch end ;
- nextch
- until chartp[ch] in [special,illegal,chstrquo,chcolon,
- chperiod,chlt,chgt,chlparen,chspace];
- if k >= kk then kk := k
- else
- repeat id[kk] := ' '; kk := kk - 1
- until kk = k;
- for i := frw[k] to frw[k+1] - 1 do
- if rw[i] = id then
- begin sy := rsy[i]; op := rop[i]; goto 2 end;
- sy := ident; op := noop;
- 2: end;
- number:
- begin op := noop; i := 0;
- repeat i := i+1; if i<= digmax then digit[i] := ch; nextch
- until chartp[ch] <> number;
- if ((ch = '.') and (input^ <> '.')) or (ch = 'e') then
- begin
- k := i;
- if ch = '.' then
- begin k := k+1; if k <= digmax then digit[k] := ch;
- nextch; (*if ch = '.' then begin ch := ':'; goto 3 end;*)
- if chartp[ch] <> number then error(201)
- else
- repeat k := k + 1;
- if k <= digmax then digit[k] := ch; nextch
- until chartp[ch] <> number
- end;
- if ch = 'e' then
- begin k := k+1; if k <= digmax then digit[k] := ch;
- nextch;
- if (ch = '+') or (ch ='-') then
- begin k := k+1; if k <= digmax then digit[k] := ch;
- nextch
- end;
- if chartp[ch] <> number then error(201)
- else
- repeat k := k+1;
- if k <= digmax then digit[k] := ch; nextch
- until chartp[ch] <> number
- end;
- new(lvp,reel); sy:= realconst; lvp^.cclass := reel;
- with lvp^ do
- begin for i := 1 to strglgth do rval[i] := ' ';
- if k <= digmax then
- for i := 2 to k + 1 do rval[i] := digit[i-1]
- else begin error(203); rval[2] := '0';
- rval[3] := '.'; rval[4] := '0'
- end
- end;
- val.valp := lvp
- end
- else
- 3: begin
- if i > digmax then begin error(203); val.ival := 0 end
- else
- with val do
- begin ival := 0;
- for k := 1 to i do
- begin
- if ival <= mxint10 then
- ival := ival*10+ordint[digit[k]]
- else begin error(203); ival := 0 end
- end;
- sy := intconst
- end
- end
- end;
- chstrquo:
- begin lgth := 0; sy := stringconst; op := noop;
- repeat
- repeat nextch; lgth := lgth + 1;
- if lgth <= strglgth then string[lgth] := ch
- until (eol) or (ch = '''');
- if eol then error(202) else nextch
- until ch <> '''';
- lgth := lgth - 1; (*now lgth = nr of chars in string*)
- if lgth = 0 then error(205) else
- if lgth = 1 then val.ival := ord(string[1])
- else
- begin new(lvp,strg); lvp^.cclass:=strg;
- if lgth > strglgth then
- begin error(399); lgth := strglgth end;
- with lvp^ do
- begin slgth := lgth;
- for i := 1 to lgth do sval[i] := string[i]
- end;
- val.valp := lvp
- end
- end;
- chcolon:
- begin op := noop; nextch;
- if ch = '=' then
- begin sy := becomes; nextch end
- else sy := colon
- end;
- chperiod:
- begin op := noop; nextch;
- if ch = '.' then
- begin sy := colon; nextch end
- else sy := period
- end;
- chlt:
- begin nextch; sy := relop;
- if ch = '=' then
- begin op := leop; nextch end
- else
- if ch = '>' then
- begin op := neop; nextch end
- else op := ltop
- end;
- chgt:
- begin nextch; sy := relop;
- if ch = '=' then
- begin op := geop; nextch end
- else op := gtop
- end;
- chlparen:
- begin nextch;
- if ch = '*' then
- begin nextch;
- if ch = '$' then options;
- repeat
- while (ch <> '*') and not eof(input) do nextch;
- nextch
- until (ch = ')') or eof(input);
- nextch; goto 1
- end;
- sy := lparent; op := noop
- end;
- special:
- begin sy := ssy[ch]; op := sop[ch];
- nextch
- end;
- chspace: sy := othersy
- end (*case*)
- end (*insymbol*) ;
-
- procedure enterid(fcp: ctp);
- (*enter id pointed at by fcp into the name-table,
- which on each declaration level is organised as
- an unbalanced binary tree*)
- var nam: alpha; lcp, lcp1: ctp; lleft: boolean;
- begin nam := fcp^.name;
- lcp := display[top].fname;
- if lcp = nil then
- display[top].fname := fcp
- else
- begin
- repeat lcp1 := lcp;
- if lcp^.name = nam then (*name conflict, follow right link*)
- begin error(101); lcp := lcp^.rlink; lleft := false end
- else
- if lcp^.name < nam then
- begin lcp := lcp^.rlink; lleft := false end
- else begin lcp := lcp^.llink; lleft := true end
- until lcp = nil;
- if lleft then lcp1^.llink := fcp else lcp1^.rlink := fcp
- end;
- fcp^.llink := nil; fcp^.rlink := nil
- end (*enterid*) ;
-
- procedure searchsection(fcp: ctp; var fcp1: ctp);
- (*to find record fields and forward declared procedure id's
- --> procedure proceduredeclaration
- --> procedure selector*)
- label 1;
- begin
- while fcp <> nil do
- if fcp^.name = id then goto 1
- else if fcp^.name < id then fcp := fcp^.rlink
- else fcp := fcp^.llink;
- 1: fcp1 := fcp
- end (*searchsection*) ;
-
- procedure searchid(fidcls: setofids; var fcp: ctp);
- label 1;
- var lcp: ctp;
- begin
- for disx := top downto 0 do
- begin lcp := display[disx].fname;
- while lcp <> nil do
- if lcp^.name = id then
- if lcp^.klass in fidcls then goto 1
- else
- begin if prterr then error(103);
- lcp := lcp^.rlink
- end
- else
- if lcp^.name < id then
- lcp := lcp^.rlink
- else lcp := lcp^.llink
- end;
- (*search not successful; suppress error message in case
- of forward referenced type id in pointer type definition
- --> procedure simpletype*)
- if prterr then
- begin error(104);
- (*to avoid returning nil, reference an entry
- for an undeclared id of appropriate class
- --> procedure enterundecl*)
- if types in fidcls then lcp := utypptr
- else
- if vars in fidcls then lcp := uvarptr
- else
- if field in fidcls then lcp := ufldptr
- else
- if konst in fidcls then lcp := ucstptr
- else
- if proc in fidcls then lcp := uprcptr
- else lcp := ufctptr;
- end;
- 1: fcp := lcp
- end (*searchid*) ;
-
- procedure getbounds(fsp: stp; var fmin,fmax: integer);
- (*get internal bounds of subrange or scalar type*)
- (*assume fsp<>intptr and fsp<>realptr*)
- begin
- fmin := 0; fmax := 0;
- if fsp <> nil then
- with fsp^ do
- if form = subrange then
- begin fmin := min.ival; fmax := max.ival end
- else
- if fsp = charptr then
- begin fmin := ordminchar; fmax := ordmaxchar
- end
- else
- if fconst <> nil then
- fmax := fconst^.values.ival
- end (*getbounds*) ;
-
- function alignquot(fsp: stp): integer;
- begin
- alignquot := 1;
- if fsp <> nil then
- with fsp^ do
- case form of
- scalar: if fsp=intptr then alignquot := intal
- else if fsp=boolptr then alignquot := boolal
- else if scalkind=declared then alignquot := intal
- else if fsp=charptr then alignquot := charal
- else if fsp=realptr then alignquot := realal
- else (*parmptr*) alignquot := parmal;
- subrange: alignquot := alignquot(rangetype);
- pointer: alignquot := adral;
- power: alignquot := setal;
- files: alignquot := fileal;
- arrays: alignquot := alignquot(aeltype);
- records: alignquot := recal;
- variant,tagfld: error(501)
- end
- end (*alignquot*);
-
- procedure align(fsp: stp; var flc: addrrange);
- var k,l: integer;
- begin
- k := alignquot(fsp);
- l := flc-1;
- flc := l + k - (k+l) mod k
- end (*align*);
-
- procedure printtables(fb: boolean);
- (*print data structure and name table*)
- var i, lim: disprange;
-
- procedure marker;
- (*mark data structure entries to avoid multiple printout*)
- var i: integer;
-
- procedure markctp(fp: ctp); forward;
-
- procedure markstp(fp: stp);
- (*mark data structures, prevent cycles*)
- begin
- if fp <> nil then
- with fp^ do
- begin marked := true;
- case form of
- scalar: ;
- subrange: markstp(rangetype);
- pointer: (*don't mark eltype: cycle possible; will be marked
- anyway, if fp = true*) ;
- power: markstp(elset) ;
- arrays: begin markstp(aeltype); markstp(inxtype) end;
- records: begin markctp(fstfld); markstp(recvar) end;
- files: markstp(filtype);
- tagfld: markstp(fstvar);
- variant: begin markstp(nxtvar); markstp(subvar) end
- end (*case*)
- end (*with*)
- end (*markstp*);
-
- procedure markctp;
- begin
- if fp <> nil then
- with fp^ do
- begin markctp(llink); markctp(rlink);
- markstp(idtype)
- end
- end (*markctp*);
-
- begin (*marker*)
- for i := top downto lim do
- markctp(display[i].fname)
- end (*marker*);
-
- procedure followctp(fp: ctp); forward;
-
- procedure followstp(fp: stp);
- begin
- if fp <> nil then
- with fp^ do
- if marked then
- begin marked := false; write(output,' ':4,ord(fp):6,size:10);
- case form of
- scalar: begin write(output,'scalar':10);
- if scalkind = standard then
- write(output,'standard':10)
- else write(output,'declared':10,' ':4,ord(fconst):6);
- writeln(output)
- end;
- subrange: begin
- write(output,'subrange':10,' ':4,ord(rangetype):6);
- if rangetype <> realptr then
- write(output,min.ival,max.ival)
- else
- if (min.valp <> nil) and (max.valp <> nil) then
- write(output,' ',min.valp^.rval:9,
- ' ',max.valp^.rval:9);
- writeln(output); followstp(rangetype);
- end;
- pointer: writeln(output,'pointer':10,' ':4,ord(eltype):6);
- power: begin writeln(output,'set':10,' ':4,ord(elset):6);
- followstp(elset)
- end;
- arrays: begin
- writeln(output,'array':10,' ':4,ord(aeltype):6,' ':4,
- ord(inxtype):6);
- followstp(aeltype); followstp(inxtype)
- end;
- records: begin
- writeln(output,'record':10,' ':4,ord(fstfld):6,' ':4,
- ord(recvar):6); followctp(fstfld);
- followstp(recvar)
- end;
- files: begin write(output,'file':10,' ':4,ord(filtype):6);
- followstp(filtype)
- end;
- tagfld: begin writeln(output,'tagfld':10,' ':4,ord(tagfieldp):6,
- ' ':4,ord(fstvar):6);
- followstp(fstvar)
- end;
- variant: begin writeln(output,'variant':10,' ':4,ord(nxtvar):6,
- ' ':4,ord(subvar):6,varval.ival);
- followstp(nxtvar); followstp(subvar)
- end
- end (*case*)
- end (*if marked*)
- end (*followstp*);
-
- procedure followctp;
- var i: integer;
- begin
- if fp <> nil then
- with fp^ do
- begin write(output,' ':4,ord(fp):6,' ',name:9,' ':4,ord(llink):6,
- ' ':4,ord(rlink):6,' ':4,ord(idtype):6);
- case klass of
- types: write(output,'type':10);
- konst: begin write(output,'constant':10,' ':4,ord(next):6);
- if idtype <> nil then
- if idtype = realptr then
- begin
- if values.valp <> nil then
- write(output,' ',values.valp^.rval:9)
- end
- else
- if idtype^.form = arrays then (*stringconst*)
- begin
- if values.valp <> nil then
- begin write(output,' ');
- with values.valp^ do
- for i := 1 to slgth do
- write(output,sval[i])
- end
- end
- else write(output,values.ival)
- end;
- vars: begin write(output,'variable':10);
- if vkind = actual then write(output,'actual':10)
- else write(output,'formal':10);
- write(output,' ':4,ord(next):6,vlev,' ':4,vaddr:6 );
- end;
- field: write(output,'field':10,' ':4,ord(next):6,' ':4,fldaddr:6);
- proc,
- func: begin
- if klass = proc then write(output,'procedure':10)
- else write(output,'function':10);
- if pfdeckind = standard then
- write(output,'standard':10, key:10)
- else
- begin write(output,'declared':10,' ':4,ord(next):6);
- write(output,pflev,' ':4,pfname:6);
- if pfkind = actual then
- begin write(output,'actual':10);
- if forwdecl then write(output,'forward':10)
- else write(output,'notforward':10);
- if externl then write(output,'extern':10)
- else write(output,'not extern':10);
- end
- else write(output,'formal':10)
- end
- end
- end (*case*);
- writeln(output);
- followctp(llink); followctp(rlink);
- followstp(idtype)
- end (*with*)
- end (*followctp*);
-
- begin (*printtables*)
- writeln(output); writeln(output); writeln(output);
- if fb then lim := 0
- else begin lim := top; write(output,' local') end;
- writeln(output,' tables '); writeln(output);
- marker;
- for i := top downto lim do
- followctp(display[i].fname);
- writeln(output);
- if not eol then write(output,' ':chcnt+16)
- end (*printtables*);
-
- procedure genlabel(var nxtlab: integer);
- begin intlabel := intlabel + 1;
- nxtlab := intlabel
- end (*genlabel*);
-
- procedure block(fsys: setofsys; fsy: symbol; fprocp: ctp);
- var lsy: symbol; test: boolean;
-
- procedure skip(fsys: setofsys);
- (*skip input string until relevant symbol found*)
- begin
- if not eof(input) then
- begin while not(sy in fsys) and (not eof(input)) do insymbol;
- if not (sy in fsys) then insymbol
- end
- end (*skip*) ;
-
- procedure constant(fsys: setofsys; var fsp: stp; var fvalu: valu);
- var lsp: stp; lcp: ctp; sign: (none,pos,neg);
- lvp: csp; i: 2..strglgth;
- begin lsp := nil; fvalu.ival := 0;
- if not(sy in constbegsys) then
- begin error(50); skip(fsys+constbegsys) end;
- if sy in constbegsys then
- begin
- if sy = stringconst then
- begin
- if lgth = 1 then lsp := charptr
- else
- begin
- new(lsp,arrays);
- with lsp^ do
- begin aeltype := charptr; inxtype := nil;
- size := lgth*charsize; form := arrays
- end
- end;
- fvalu := val; insymbol
- end
- else
- begin
- sign := none;
- if (sy = addop) and (op in [plus,minus]) then
- begin if op = plus then sign := pos else sign := neg;
- insymbol
- end;
- if sy = ident then
- begin searchid([konst],lcp);
- with lcp^ do
- begin lsp := idtype; fvalu := values end;
- if sign <> none then
- if lsp = intptr then
- begin if sign = neg then fvalu.ival := -fvalu.ival end
- else
- if lsp = realptr then
- begin
- if sign = neg then
- begin new(lvp,reel);
- if fvalu.valp^.rval[1] = '-' then
- lvp^.rval[1] := '+'
- else lvp^.rval[1] := '-';
- for i := 2 to strglgth do
- lvp^.rval[i] := fvalu.valp^.rval[i];
- fvalu.valp := lvp;
- end
- end
- else error(105);
- insymbol;
- end
- else
- if sy = intconst then
- begin if sign = neg then val.ival := -val.ival;
- lsp := intptr; fvalu := val; insymbol
- end
- else
- if sy = realconst then
- begin if sign = neg then val.valp^.rval[1] := '-';
- lsp := realptr; fvalu := val; insymbol
- end
- else
- begin error(106); skip(fsys) end
- end;
- if not (sy in fsys) then
- begin error(6); skip(fsys) end
- end;
- fsp := lsp
- end (*constant*) ;
-
- function equalbounds(fsp1,fsp2: stp): boolean;
- var lmin1,lmin2,lmax1,lmax2: integer;
- begin
- if (fsp1=nil) or (fsp2=nil) then equalbounds := true
- else
- begin
- getbounds(fsp1,lmin1,lmax1);
- getbounds(fsp2,lmin2,lmax2);
- equalbounds := (lmin1=lmin2) and (lmax1=lmax2)
- end
- end (*equalbounds*) ;
-
- function comptypes(fsp1,fsp2: stp) : boolean;
- (*decide whether structures pointed at by fsp1 and fsp2 are compatible*)
- var nxt1,nxt2: ctp; comp: boolean;
- ltestp1,ltestp2 : testp;
- begin
- if fsp1 = fsp2 then comptypes := true
- else
- if (fsp1 <> nil) and (fsp2 <> nil) then
- if fsp1^.form = fsp2^.form then
- case fsp1^.form of
- scalar:
- comptypes := false;
- (* identical scalars declared on different levels are
- not recognized to be compatible*)
- subrange:
- comptypes := comptypes(fsp1^.rangetype,fsp2^.rangetype);
- pointer:
- begin
- comp := false; ltestp1 := globtestp;
- ltestp2 := globtestp;
- while ltestp1 <> nil do
- with ltestp1^ do
- begin
- if (elt1 = fsp1^.eltype) and
- (elt2 = fsp2^.eltype) then comp := true;
- ltestp1 := lasttestp
- end;
- if not comp then
- begin new(ltestp1);
- with ltestp1^ do
- begin elt1 := fsp1^.eltype;
- elt2 := fsp2^.eltype;
- lasttestp := globtestp
- end;
- globtestp := ltestp1;
- comp := comptypes(fsp1^.eltype,fsp2^.eltype)
- end;
- comptypes := comp; globtestp := ltestp2
- end;
- power:
- comptypes := comptypes(fsp1^.elset,fsp2^.elset);
- arrays:
- begin
- comp := comptypes(fsp1^.aeltype,fsp2^.aeltype)
- and comptypes(fsp1^.inxtype,fsp2^.inxtype);
- comptypes := comp and (fsp1^.size = fsp2^.size) and
- equalbounds(fsp1^.inxtype,fsp2^.inxtype)
- end;
- records:
- begin nxt1 := fsp1^.fstfld; nxt2 := fsp2^.fstfld; comp:=true;
- while (nxt1 <> nil) and (nxt2 <> nil) do
- begin comp:=comp and comptypes(nxt1^.idtype,nxt2^.idtype);
- nxt1 := nxt1^.next; nxt2 := nxt2^.next
- end;
- comptypes := comp and (nxt1 = nil) and (nxt2 = nil)
- and(fsp1^.recvar = nil)and(fsp2^.recvar = nil)
- end;
- (*identical records are recognized to be compatible
- iff no variants occur*)
- files:
- comptypes := comptypes(fsp1^.filtype,fsp2^.filtype)
- end (*case*)
- else (*fsp1^.form <> fsp2^.form*)
- if fsp1^.form = subrange then
- comptypes := comptypes(fsp1^.rangetype,fsp2)
- else
- if fsp2^.form = subrange then
- comptypes := comptypes(fsp1,fsp2^.rangetype)
- else comptypes := false
- else comptypes := true
- end (*comptypes*) ;
-
- function string(fsp: stp) : boolean;
- begin string := false;
- if fsp <> nil then
- if fsp^.form = arrays then
- if comptypes(fsp^.aeltype,charptr) then string := true
- end (*string*) ;
-
- procedure typ(fsys: setofsys; var fsp: stp; var fsize: addrrange);
- var lsp,lsp1,lsp2: stp; oldtop: disprange; lcp: ctp;
- lsize,displ: addrrange; lmin,lmax: integer;
-
- procedure simpletype(fsys:setofsys; var fsp:stp; var fsize:addrrange);
- var lsp,lsp1: stp; lcp,lcp1: ctp; ttop: disprange;
- lcnt: integer; lvalu: valu;
- begin fsize := 1;
- if not (sy in simptypebegsys) then
- begin error(1); skip(fsys + simptypebegsys) end;
- if sy in simptypebegsys then
- begin
- if sy = lparent then
- begin ttop := top; (*decl. consts local to innermost block*)
- while display[top].occur <> blck do top := top - 1;
- new(lsp,scalar,declared);
- with lsp^ do
- begin size := intsize; form := scalar;
- scalkind := declared
- end;
- lcp1 := nil; lcnt := 0;
- repeat insymbol;
- if sy = ident then
- begin new(lcp,konst);
- with lcp^ do
- begin name := id; idtype := lsp; next := lcp1;
- values.ival := lcnt; klass := konst
- end;
- enterid(lcp);
- lcnt := lcnt + 1;
- lcp1 := lcp; insymbol
- end
- else error(2);
- if not (sy in fsys + [comma,rparent]) then
- begin error(6); skip(fsys + [comma,rparent]) end
- until sy <> comma;
- lsp^.fconst := lcp1; top := ttop;
- if sy = rparent then insymbol else error(4)
- end
- else
- begin
- if sy = ident then
- begin searchid([types,konst],lcp);
- insymbol;
- if lcp^.klass = konst then
- begin new(lsp,subrange);
- with lsp^, lcp^ do
- begin rangetype := idtype; form := subrange;
- if string(rangetype) then
- begin error(148); rangetype := nil end;
- min := values; size := intsize
- end;
- if sy = colon then insymbol else error(5);
- constant(fsys,lsp1,lvalu);
- lsp^.max := lvalu;
- if lsp^.rangetype <> lsp1 then error(107)
- end
- else
- begin lsp := lcp^.idtype;
- if lsp <> nil then fsize := lsp^.size
- end
- end (*sy = ident*)
- else
- begin new(lsp,subrange); lsp^.form := subrange;
- constant(fsys + [colon],lsp1,lvalu);
- if string(lsp1) then
- begin error(148); lsp1 := nil end;
- with lsp^ do
- begin rangetype:=lsp1; min:=lvalu; size:=intsize end;
- if sy = colon then insymbol else error(5);
- constant(fsys,lsp1,lvalu);
- lsp^.max := lvalu;
- if lsp^.rangetype <> lsp1 then error(107)
- end;
- if lsp <> nil then
- with lsp^ do
- if form = subrange then
- if rangetype <> nil then
- if rangetype = realptr then error(399)
- else
- if min.ival > max.ival then error(102)
- end;
- fsp := lsp;
- if not (sy in fsys) then
- begin error(6); skip(fsys) end
- end
- else fsp := nil
- end (*simpletype*) ;
-
- procedure fieldlist(fsys: setofsys; var frecvar: stp);
- var lcp,lcp1,nxt,nxt1: ctp; lsp,lsp1,lsp2,lsp3,lsp4: stp;
- minsize,maxsize,lsize: addrrange; lvalu: valu;
- begin nxt1 := nil; lsp := nil;
- if not (sy in (fsys+[ident,casesy])) then
- begin error(19); skip(fsys + [ident,casesy]) end;
- while sy = ident do
- begin nxt := nxt1;
- repeat
- if sy = ident then
- begin new(lcp,field);
- with lcp^ do
- begin name := id; idtype := nil; next := nxt;
- klass := field
- end;
- nxt := lcp;
- enterid(lcp);
- insymbol
- end
- else error(2);
- if not (sy in [comma,colon]) then
- begin error(6); skip(fsys + [comma,colon,semicolon,casesy])
- end;
- test := sy <> comma;
- if not test then insymbol
- until test;
- if sy = colon then insymbol else error(5);
- typ(fsys + [casesy,semicolon],lsp,lsize);
- while nxt <> nxt1 do
- with nxt^ do
- begin align(lsp,displ);
- idtype := lsp; fldaddr := displ;
- nxt := next; displ := displ + lsize
- end;
- nxt1 := lcp;
- while sy = semicolon do
- begin insymbol;
- if not (sy in fsys + [ident,casesy,semicolon]) then
- begin error(19); skip(fsys + [ident,casesy]) end
- end
- end (*while*);
- nxt := nil;
- while nxt1 <> nil do
- with nxt1^ do
- begin lcp := next; next := nxt; nxt := nxt1; nxt1 := lcp end;
- if sy = casesy then
- begin new(lsp,tagfld);
- with lsp^ do
- begin tagfieldp := nil; fstvar := nil; form:=tagfld end;
- frecvar := lsp;
- insymbol;
- if sy = ident then
- begin new(lcp,field);
- with lcp^ do
- begin name := id; idtype := nil; klass:=field;
- next := nil; fldaddr := displ
- end;
- enterid(lcp);
- insymbol;
- if sy = colon then insymbol else error(5);
- if sy = ident then
- begin searchid([types],lcp1);
- lsp1 := lcp1^.idtype;
- if lsp1 <> nil then
- begin align(lsp1,displ);
- lcp^.fldaddr := displ;
- displ := displ+lsp1^.size;
- if (lsp1^.form <= subrange) or string(lsp1) then
- begin if comptypes(realptr,lsp1) then error(109)
- else if string(lsp1) then error(399);
- lcp^.idtype := lsp1; lsp^.tagfieldp := lcp;
- end
- else error(110);
- end;
- insymbol;
- end
- else begin error(2); skip(fsys + [ofsy,lparent]) end
- end
- else begin error(2); skip(fsys + [ofsy,lparent]) end;
- lsp^.size := displ;
- if sy = ofsy then insymbol else error(8);
- lsp1 := nil; minsize := displ; maxsize := displ;
- repeat lsp2 := nil;
- if not (sy in fsys + [semicolon]) then
- begin
- repeat constant(fsys + [comma,colon,lparent],lsp3,lvalu);
- if lsp^.tagfieldp <> nil then
- if not comptypes(lsp^.tagfieldp^.idtype,lsp3)then error(111);
- new(lsp3,variant);
- with lsp3^ do
- begin nxtvar := lsp1; subvar := lsp2; varval := lvalu;
- form := variant
- end;
- lsp4 := lsp1;
- while lsp4 <> nil do
- with lsp4^ do
- begin
- if varval.ival = lvalu.ival then error(178);
- lsp4 := nxtvar
- end;
- lsp1 := lsp3; lsp2 := lsp3;
- test := sy <> comma;
- if not test then insymbol
- until test;
- if sy = colon then insymbol else error(5);
- if sy = lparent then insymbol else error(9);
- fieldlist(fsys + [rparent,semicolon],lsp2);
- if displ > maxsize then maxsize := displ;
- while lsp3 <> nil do
- begin lsp4 := lsp3^.subvar; lsp3^.subvar := lsp2;
- lsp3^.size := displ;
- lsp3 := lsp4
- end;
- if sy = rparent then
- begin insymbol;
- if not (sy in fsys + [semicolon]) then
- begin error(6); skip(fsys + [semicolon]) end
- end
- else error(4);
- end;
- test := sy <> semicolon;
- if not test then
- begin displ := minsize;
- insymbol
- end
- until test;
- displ := maxsize;
- lsp^.fstvar := lsp1;
- end
- else frecvar := nil
- end (*fieldlist*) ;
-
- begin (*typ*)
- if not (sy in typebegsys) then
- begin error(10); skip(fsys + typebegsys) end;
- if sy in typebegsys then
- begin
- if sy in simptypebegsys then simpletype(fsys,fsp,fsize)
- else
- (*^*) if sy = arrow then
- begin new(lsp,pointer); fsp := lsp;
- with lsp^ do
- begin eltype := nil; size := ptrsize; form:=pointer end;
- insymbol;
- if sy = ident then
- begin prterr := false; (*no error if search not successful*)
- searchid([types],lcp); prterr := true;
- if lcp = nil then (*forward referenced type id*)
- begin new(lcp,types);
- with lcp^ do
- begin name := id; idtype := lsp;
- next := fwptr; klass := types
- end;
- fwptr := lcp
- end
- else
- begin
- if lcp^.idtype <> nil then
- if lcp^.idtype^.form = files then error(108)
- else lsp^.eltype := lcp^.idtype
- end;
- insymbol;
- end
- else error(2);
- end
- else
- begin
- if sy = packedsy then
- begin insymbol;
- if not (sy in typedels) then
- begin
- error(10); skip(fsys + typedels)
- end
- end;
- (*array*) if sy = arraysy then
- begin insymbol;
- if sy = lbrack then insymbol else error(11);
- lsp1 := nil;
- repeat new(lsp,arrays);
- with lsp^ do
- begin aeltype := lsp1; inxtype := nil; form:=arrays end;
- lsp1 := lsp;
- simpletype(fsys + [comma,rbrack,ofsy],lsp2,lsize);
- lsp1^.size := lsize;
- if lsp2 <> nil then
- if lsp2^.form <= subrange then
- begin
- if lsp2 = realptr then
- begin error(109); lsp2 := nil end
- else
- if lsp2 = intptr then
- begin error(149); lsp2 := nil end;
- lsp^.inxtype := lsp2
- end
- else begin error(113); lsp2 := nil end;
- test := sy <> comma;
- if not test then insymbol
- until test;
- if sy = rbrack then insymbol else error(12);
- if sy = ofsy then insymbol else error(8);
- typ(fsys,lsp,lsize);
- repeat
- with lsp1^ do
- begin lsp2 := aeltype; aeltype := lsp;
- if inxtype <> nil then
- begin getbounds(inxtype,lmin,lmax);
- align(lsp,lsize);
- lsize := lsize*(lmax - lmin + 1);
- size := lsize
- end
- end;
- lsp := lsp1; lsp1 := lsp2
- until lsp1 = nil
- end
- else
- (*record*) if sy = recordsy then
- begin insymbol;
- oldtop := top;
- if top < displimit then
- begin top := top + 1;
- with display[top] do
- begin fname := nil;
- flabel := nil;
- occur := rec
- end
- end
- else error(250);
- displ := 0;
- fieldlist(fsys-[semicolon]+[endsy],lsp1);
- new(lsp,records);
- with lsp^ do
- begin fstfld := display[top].fname;
- recvar := lsp1; size := displ; form := records
- end;
- top := oldtop;
- if sy = endsy then insymbol else error(13)
- end
- else
- (*set*) if sy = setsy then
- begin insymbol;
- if sy = ofsy then insymbol else error(8);
- simpletype(fsys,lsp1,lsize);
- if lsp1 <> nil then
- if lsp1^.form > subrange then
- begin error(115); lsp1 := nil end
- else
- if lsp1 = realptr then
- begin error(114); lsp1 := nil end
- else if lsp1 = intptr then
- begin error(169); lsp1 := nil end
- else
- begin getbounds(lsp1,lmin,lmax);
- if (lmin < setlow) or (lmax > sethigh)
- then error(169);
- end;
- new(lsp,power);
- with lsp^ do
- begin elset:=lsp1; size:=setsize; form:=power end;
- end
- else
- (*file*) if sy = filesy then
- begin insymbol;
- error(399); skip(fsys); lsp := nil
- end;
- fsp := lsp
- end;
- if not (sy in fsys) then
- begin error(6); skip(fsys) end
- end
- else fsp := nil;
- if fsp = nil then fsize := 1 else fsize := fsp^.size
- end (*typ*) ;
-
- procedure labeldeclaration;
- var llp: lbp; redef: boolean; lbname: integer;
- begin
- repeat
- if sy = intconst then
- with display[top] do
- begin llp := flabel; redef := false;
- while (llp <> nil) and not redef do
- if llp^.labval <> val.ival then
- llp := llp^.nextlab
- else begin redef := true; error(166) end;
- if not redef then
- begin new(llp);
- with llp^ do
- begin labval := val.ival; genlabel(lbname);
- defined := false; nextlab := flabel; labname := lbname
- end;
- flabel := llp
- end;
- insymbol
- end
- else error(15);
- if not ( sy in fsys + [comma, semicolon] ) then
- begin error(6); skip(fsys+[comma,semicolon]) end;
- test := sy <> comma;
- if not test then insymbol
- until test;
- if sy = semicolon then insymbol else error(14)
- end (* labeldeclaration *) ;
-
- procedure constdeclaration;
- var lcp: ctp; lsp: stp; lvalu: valu;
- begin
- if sy <> ident then
- begin error(2); skip(fsys + [ident]) end;
- while sy = ident do
- begin new(lcp,konst);
- with lcp^ do
- begin name := id; idtype := nil; next := nil; klass:=konst end;
- insymbol;
- if (sy = relop) and (op = eqop) then insymbol else error(16);
- constant(fsys + [semicolon],lsp,lvalu);
- enterid(lcp);
- lcp^.idtype := lsp; lcp^.values := lvalu;
- if sy = semicolon then
- begin insymbol;
- if not (sy in fsys + [ident]) then
- begin error(6); skip(fsys + [ident]) end
- end
- else error(14)
- end
- end (*constdeclaration*) ;
-
- procedure typedeclaration;
- var lcp,lcp1,lcp2: ctp; lsp: stp; lsize: addrrange;
- begin
- if sy <> ident then
- begin error(2); skip(fsys + [ident]) end;
- while sy = ident do
- begin new(lcp,types);
- with lcp^ do
- begin name := id; idtype := nil; klass := types end;
- insymbol;
- if (sy = relop) and (op = eqop) then insymbol else error(16);
- typ(fsys + [semicolon],lsp,lsize);
- enterid(lcp);
- lcp^.idtype := lsp;
- (*has any forward reference been satisfied:*)
- lcp1 := fwptr;
- while lcp1 <> nil do
- begin
- if lcp1^.name = lcp^.name then
- begin lcp1^.idtype^.eltype := lcp^.idtype;
- if lcp1 <> fwptr then
- lcp2^.next := lcp1^.next
- else fwptr := lcp1^.next;
- end
- else lcp2 := lcp1;
- lcp1 := lcp1^.next
- end;
- if sy = semicolon then
- begin insymbol;
- if not (sy in fsys + [ident]) then
- begin error(6); skip(fsys + [ident]) end
- end
- else error(14)
- end;
- if fwptr <> nil then
- begin error(117); writeln(output);
- repeat writeln(output,' type-id ',fwptr^.name);
- fwptr := fwptr^.next
- until fwptr = nil;
- if not eol then write(output,' ': chcnt+16)
- end
- end (*typedeclaration*) ;
-
- procedure vardeclaration;
- var lcp,nxt: ctp; lsp: stp; lsize: addrrange;
- begin nxt := nil;
- repeat
- repeat
- if sy = ident then
- begin new(lcp,vars);
- with lcp^ do
- begin name := id; next := nxt; klass := vars;
- idtype := nil; vkind := actual; vlev := level
- end;
- enterid(lcp);
- nxt := lcp;
- insymbol;
- end
- else error(2);
- if not (sy in fsys + [comma,colon] + typedels) then
- begin error(6); skip(fsys+[comma,colon,semicolon]+typedels) end;
- test := sy <> comma;
- if not test then insymbol
- until test;
- if sy = colon then insymbol else error(5);
- typ(fsys + [semicolon] + typedels,lsp,lsize);
- while nxt <> nil do
- with nxt^ do
- begin align(lsp,lc);
- idtype := lsp; vaddr := lc;
- lc := lc + lsize; nxt := next
- end;
- if sy = semicolon then
- begin insymbol;
- if not (sy in fsys + [ident]) then
- begin error(6); skip(fsys + [ident]) end
- end
- else error(14)
- until (sy <> ident) and not (sy in typedels);
- if fwptr <> nil then
- begin error(117); writeln(output);
- repeat writeln(output,' type-id ',fwptr^.name);
- fwptr := fwptr^.next
- until fwptr = nil;
- if not eol then write(output,' ': chcnt+16)
- end
- end (*vardeclaration*) ;
-
- procedure procdeclaration(fsy: symbol);
- var oldlev: 0..maxlevel; lcp,lcp1: ctp; lsp: stp;
- forw: boolean; oldtop: disprange;
- llc,lcm: addrrange; lbname: integer; markp: marktype;
-
- procedure parameterlist(fsy: setofsys; var fpar: ctp);
- var lcp,lcp1,lcp2,lcp3: ctp; lsp: stp; lkind: idkind;
- llc,lsize: addrrange; count: integer;
- begin lcp1 := nil;
- if not (sy in fsy + [lparent]) then
- begin error(7); skip(fsys + fsy + [lparent]) end;
- if sy = lparent then
- begin if forw then error(119);
- insymbol;
- if not (sy in [ident,varsy,procsy,funcsy]) then
- begin error(7); skip(fsys + [ident,rparent]) end;
- while sy in [ident,varsy,procsy,funcsy] do
- begin
- if sy = procsy then
- begin error(399);
- repeat insymbol;
- if sy = ident then
- begin new(lcp,proc,declared,formal);
- with lcp^ do
- begin name := id; idtype := nil; next := lcp1;
- pflev := level (*beware of parameter procedures*);
- klass:=proc;pfdeckind:=declared;pfkind:=formal
- end;
- enterid(lcp);
- lcp1 := lcp;
- align(parmptr,lc);
- (*lc := lc + some size *)
- insymbol
- end
- else error(2);
- if not (sy in fsys + [comma,semicolon,rparent]) then
- begin error(7);skip(fsys+[comma,semicolon,rparent])end
- until sy <> comma
- end
- else
- begin
- if sy = funcsy then
- begin error(399); lcp2 := nil;
- repeat insymbol;
- if sy = ident then
- begin new(lcp,func,declared,formal);
- with lcp^ do
- begin name := id; idtype := nil; next := lcp2;
- pflev := level (*beware param funcs*);
- klass:=func;pfdeckind:=declared;
- pfkind:=formal
- end;
- enterid(lcp);
- lcp2 := lcp;
- align(parmptr,lc);
- (*lc := lc + some size*)
- insymbol;
- end;
- if not (sy in [comma,colon] + fsys) then
- begin error(7);skip(fsys+[comma,semicolon,rparent])
- end
- until sy <> comma;
- if sy = colon then
- begin insymbol;
- if sy = ident then
- begin searchid([types],lcp);
- lsp := lcp^.idtype;
- if lsp <> nil then
- if not(lsp^.form in[scalar,subrange,pointer])
- then begin error(120); lsp := nil end;
- lcp3 := lcp2;
- while lcp2 <> nil do
- begin lcp2^.idtype := lsp; lcp := lcp2;
- lcp2 := lcp2^.next
- end;
- lcp^.next := lcp1; lcp1 := lcp3;
- insymbol
- end
- else error(2);
- if not (sy in fsys + [semicolon,rparent]) then
- begin error(7);skip(fsys+[semicolon,rparent])end
- end
- else error(5)
- end
- else
- begin
- if sy = varsy then
- begin lkind := formal; insymbol end
- else lkind := actual;
- lcp2 := nil;
- count := 0;
- repeat
- if sy = ident then
- begin new(lcp,vars);
- with lcp^ do
- begin name:=id; idtype:=nil; klass:=vars;
- vkind := lkind; next := lcp2; vlev := level;
- end;
- enterid(lcp);
- lcp2 := lcp; count := count+1;
- insymbol;
- end;
- if not (sy in [comma,colon] + fsys) then
- begin error(7);skip(fsys+[comma,semicolon,rparent])
- end;
- test := sy <> comma;
- if not test then insymbol
- until test;
- if sy = colon then
- begin insymbol;
- if sy = ident then
- begin searchid([types],lcp);
- lsp := lcp^.idtype;
- lsize := ptrsize;
- if lsp <> nil then
- if lkind=actual then
- if lsp^.form<=power then lsize := lsp^.size
- else if lsp^.form=files then error(121);
- align(parmptr,lsize);
- lcp3 := lcp2;
- align(parmptr,lc);
- lc := lc+count*lsize;
- llc := lc;
- while lcp2 <> nil do
- begin lcp := lcp2;
- with lcp2^ do
- begin idtype := lsp;
- llc := llc-lsize;
- vaddr := llc;
- end;
- lcp2 := lcp2^.next
- end;
- lcp^.next := lcp1; lcp1 := lcp3;
- insymbol
- end
- else error(2);
- if not (sy in fsys + [semicolon,rparent]) then
- begin error(7);skip(fsys+[semicolon,rparent])end
- end
- else error(5);
- end;
- end;
- if sy = semicolon then
- begin insymbol;
- if not (sy in fsys + [ident,varsy,procsy,funcsy]) then
- begin error(7); skip(fsys + [ident,rparent]) end
- end
- end (*while*) ;
- if sy = rparent then
- begin insymbol;
- if not (sy in fsy + fsys) then
- begin error(6); skip(fsy + fsys) end
- end
- else error(4);
- lcp3 := nil;
- (*reverse pointers and reserve local cells for copies of multiple
- values*)
- while lcp1 <> nil do
- with lcp1^ do
- begin lcp2 := next; next := lcp3;
- if klass = vars then
- if idtype <> nil then
- if (vkind=actual)and(idtype^.form>power) then
- begin align(idtype,lc);
- vaddr := lc;
- lc := lc+idtype^.size;
- end;
- lcp3 := lcp1; lcp1 := lcp2
- end;
- fpar := lcp3
- end
- else fpar := nil
- end (*parameterlist*) ;
-
- begin (*procdeclaration*)
- llc := lc; lc := lcaftermarkstack; forw := false;
- if sy = ident then
- begin searchsection(display[top].fname,lcp); (*decide whether forw.*)
- if lcp <> nil then
- begin
- if lcp^.klass = proc then
- forw := lcp^.forwdecl and(fsy=procsy)and(lcp^.pfkind=actual)
- else
- if lcp^.klass = func then
- forw:=lcp^.forwdecl and(fsy=funcsy)and(lcp^.pfkind=actual)
- else forw := false;
- if not forw then error(160)
- end;
- if not forw then
- begin
- if fsy = procsy then new(lcp,proc,declared,actual)
- else new(lcp,func,declared,actual);
- with lcp^ do
- begin name := id; idtype := nil;
- externl := false; pflev := level; genlabel(lbname);
- pfdeckind := declared; pfkind := actual; pfname := lbname;
- if fsy = procsy then klass := proc
- else klass := func
- end;
- enterid(lcp)
- end
- else
- begin lcp1 := lcp^.next;
- while lcp1 <> nil do
- begin
- with lcp1^ do
- if klass = vars then
- if idtype <> nil then
- begin lcm := vaddr + idtype^.size;
- if lcm > lc then lc := lcm
- end;
- lcp1 := lcp1^.next
- end
- end;
- insymbol
- end
- else
- begin error(2); lcp := ufctptr end;
- oldlev := level; oldtop := top;
- if level < maxlevel then level := level + 1 else error(251);
- if top < displimit then
- begin top := top + 1;
- with display[top] do
- begin
- if forw then fname := lcp^.next
- else fname := nil;
- flabel := nil;
- occur := blck
- end
- end
- else error(250);
- if fsy = procsy then
- begin parameterlist([semicolon],lcp1);
- if not forw then lcp^.next := lcp1
- end
- else
- begin parameterlist([semicolon,colon],lcp1);
- if not forw then lcp^.next := lcp1;
- if sy = colon then
- begin insymbol;
- if sy = ident then
- begin if forw then error(122);
- searchid([types],lcp1);
- lsp := lcp1^.idtype;
- lcp^.idtype := lsp;
- if lsp <> nil then
- if not (lsp^.form in [scalar,subrange,pointer]) then
- begin error(120); lcp^.idtype := nil end;
- insymbol
- end
- else begin error(2); skip(fsys + [semicolon]) end
- end
- else
- if not forw then error(123)
- end;
- if sy = semicolon then insymbol else error(14);
- if sy = forwardsy then
- begin
- if forw then error(161)
- else lcp^.forwdecl := true;
- insymbol;
- if sy = semicolon then insymbol else error(14);
- if not (sy in fsys) then
- begin error(6); skip(fsys) end
- end
- else
- begin lcp^.forwdecl := false; mark(markp);
- repeat block(fsys,semicolon,lcp);
- if sy = semicolon then
- begin if prtables then printtables(false); insymbol;
- if not (sy in [beginsy,procsy,funcsy]) then
- begin error(6); skip(fsys) end
- end
- else error(14)
- until (sy in [beginsy,procsy,funcsy]) or eof(input);
- release(markp); (* return local entries on runtime heap *)
- end;
- level := oldlev; top := oldtop; lc := llc;
- end (*procdeclaration*) ;
-
- procedure body(fsys: setofsys);
- const cstoccmax=65; cixmax=1000;
- type oprange = 0..63;
- var
- llcp:ctp; saveid:alpha;
- cstptr: array [1..cstoccmax] of csp;
- cstptrix: 0..cstoccmax;
- (*allows referencing of noninteger constants by an index
- (instead of a pointer), which can be stored in the p2-field
- of the instruction record until writeout.
- --> procedure load, procedure writeout*)
- entname, segsize: integer;
- stacktop, topnew, topmax: integer;
- lcmax,llc1: addrrange; lcp: ctp;
- llp: lbp;
-
-
- procedure mes(i: integer);
- begin topnew := topnew + cdx[i]*maxstack;
- if topnew > topmax then topmax := topnew
- end;
-
- procedure putic;
- begin if ic mod 10 = 0 then writeln(prr,'i',ic:5) end;
-
- procedure gen0(fop: oprange);
- begin
- if prcode then begin putic; writeln(prr,mn[fop]:4) end;
- ic := ic + 1; mes(fop)
- end (*gen0*) ;
-
- procedure gen1(fop: oprange; fp2: integer);
- var k: integer;
- begin
- if prcode then
- begin putic; write(prr,mn[fop]:4);
- if fop = 30 then
- begin writeln(prr,sna[fp2]:12);
- topnew := topnew + pdx[fp2]*maxstack;
- if topnew > topmax then topmax := topnew
- end
- else
- begin
- if fop = 38 then
- begin write(prr,'''');
- with cstptr[fp2]^ do
- begin
- for k := 1 to slgth do write(prr,sval[k]:1);
- for k := slgth+1 to strglgth do write(prr,' ');
- end;
- writeln(prr,'''')
- end
- else if fop = 42 then writeln(prr,chr(fp2))
- else writeln(prr,fp2:12);
- mes(fop)
- end
- end;
- ic := ic + 1
- end (*gen1*) ;
-
- procedure gen2(fop: oprange; fp1,fp2: integer);
- var k : integer;
- begin
- if prcode then
- begin putic; write(prr,mn[fop]:4);
- case fop of
- 45,50,54,56:
- writeln(prr,' ',fp1:3,fp2:8);
- 47,48,49,52,53,55:
- begin write(prr,chr(fp1));
- if chr(fp1) = 'm' then write(prr,fp2:11);
- writeln(prr)
- end;
- 51:
- case fp1 of
- 1: writeln(prr,'i ',fp2);
- 2: begin write(prr,'r ');
- with cstptr[fp2]^ do
- for k := 1 to strglgth do write(prr,rval[k]);
- writeln(prr)
- end;
- 3: writeln(prr,'b ',fp2);
- 4: writeln(prr,'n');
- 6: writeln(prr,'c ''':3,chr(fp2),'''');
- 5: begin write(prr,'(');
- with cstptr[fp2]^ do
- for k := setlow to sethigh do
- if k in pval then write(prr,k:3);
- writeln(prr,')')
- end
- end
- end;
- end;
- ic := ic + 1; mes(fop)
- end (*gen2*) ;
-
- procedure gentypindicator(fsp: stp);
- begin
- if fsp<>nil then
- with fsp^ do
- case form of
- scalar: if fsp=intptr then write(prr,'i')
- else
- if fsp=boolptr then write(prr,'b')
- else
- if fsp=charptr then write(prr,'c')
- else
- if scalkind = declared then write(prr,'i')
- else write(prr,'r');
- subrange: gentypindicator(rangetype);
- pointer: write(prr,'a');
- power: write(prr,'s');
- records,arrays: write(prr,'m');
- files,tagfld,variant: error(500)
- end
- end (*typindicator*);
-
- procedure gen0t(fop: oprange; fsp: stp);
- begin
- if prcode then
- begin putic;
- write(prr,mn[fop]:4);
- gentypindicator(fsp);
- writeln(prr);
- end;
- ic := ic + 1; mes(fop)
- end (*gen0t*);
-
- procedure gen1t(fop: oprange; fp2: integer; fsp: stp);
- begin
- if prcode then
- begin putic;
- write(prr,mn[fop]:4);
- gentypindicator(fsp);
- writeln(prr,fp2:11)
- end;
- ic := ic + 1; mes(fop)
- end (*gen1t*);
-
- procedure gen2t(fop: oprange; fp1,fp2: integer; fsp: stp);
- begin
- if prcode then
- begin putic;
- write(prr,mn[fop]: 4);
- gentypindicator(fsp);
- writeln(prr,fp1:3+5*ord(abs(fp1)>99),fp2:8);
- end;
- ic := ic + 1; mes(fop)
- end (*gen2t*);
-
- procedure load;
- begin
- with gattr do
- if typtr <> nil then
- begin
- case kind of
- cst: if (typtr^.form = scalar) and (typtr <> realptr) then
- if typtr = boolptr then gen2(51(*ldc*),3,cval.ival)
- else
- if typtr=charptr then
- gen2(51(*ldc*),6,cval.ival)
- else gen2(51(*ldc*),1,cval.ival)
- else
- if typtr = nilptr then gen2(51(*ldc*),4,0)
- else
- if cstptrix >= cstoccmax then error(254)
- else
- begin cstptrix := cstptrix + 1;
- cstptr[cstptrix] := cval.valp;
- if typtr = realptr then
- gen2(51(*ldc*),2,cstptrix)
- else
- gen2(51(*ldc*),5,cstptrix)
- end;
- varbl: case access of
- drct: if vlevel<=1 then
- gen1t(39(*ldo*),dplmt,typtr)
- else gen2t(54(*lod*),level-vlevel,dplmt,typtr);
- indrct: gen1t(35(*ind*),idplmt,typtr);
- inxd: error(400)
- end;
- expr:
- end;
- kind := expr
- end
- end (*load*) ;
-
- procedure store(var fattr: attr);
- begin
- with fattr do
- if typtr <> nil then
- case access of
- drct: if vlevel <= 1 then gen1t(43(*sro*),dplmt,typtr)
- else gen2t(56(*str*),level-vlevel,dplmt,typtr);
- indrct: if idplmt <> 0 then error(400)
- else gen0t(26(*sto*),typtr);
- inxd: error(400)
- end
- end (*store*) ;
-
- procedure loadaddress;
- begin
- with gattr do
- if typtr <> nil then
- begin
- case kind of
- cst: if string(typtr) then
- if cstptrix >= cstoccmax then error(254)
- else
- begin cstptrix := cstptrix + 1;
- cstptr[cstptrix] := cval.valp;
- gen1(38(*lca*),cstptrix)
- end
- else error(400);
- varbl: case access of
- drct: if vlevel <= 1 then gen1(37(*lao*),dplmt)
- else gen2(50(*lda*),level-vlevel,dplmt);
- indrct: if idplmt <> 0 then
- gen1t(34(*inc*),idplmt,nilptr);
- inxd: error(400)
- end;
- expr: error(400)
- end;
- kind := varbl; access := indrct; idplmt := 0
- end
- end (*loadaddress*) ;
-
-
- procedure genfjp(faddr: integer);
- begin load;
- if gattr.typtr <> nil then
- if gattr.typtr <> boolptr then error(144);
- if prcode then begin putic; writeln(prr,mn[33]:4,' l':8,faddr:4) end;
- ic := ic + 1; mes(33)
- end (*genfjp*) ;
-
- procedure genujpxjp(fop: oprange; fp2: integer);
- begin
- if prcode then
- begin putic; writeln(prr, mn[fop]:4, ' l':8,fp2:4) end;
- ic := ic + 1; mes(fop)
- end (*genujpxjp*);
-
-
- procedure gencupent(fop: oprange; fp1,fp2: integer);
- begin
- if prcode then
- begin putic;
- writeln(prr,mn[fop]:4,fp1:4,'l':4,fp2:4)
- end;
- ic := ic + 1; mes(fop)
- end;
-
-
- procedure checkbnds(fsp: stp);
- var lmin,lmax: integer;
- begin
- if fsp <> nil then
- if fsp <> intptr then
- if fsp <> realptr then
- if fsp^.form <= subrange then
- begin
- getbounds(fsp,lmin,lmax);
- gen2t(45(*chk*),lmin,lmax,fsp)
- end
- end (*checkbnds*);
-
-
- procedure putlabel(labname: integer);
- begin if prcode then writeln(prr, 'l', labname:4)
- end (*putlabel*);
-
- procedure statement(fsys: setofsys);
- label 1;
- var lcp: ctp; llp: lbp;
-
- procedure expression(fsys: setofsys); forward;
-
- procedure selector(fsys: setofsys; fcp: ctp);
- var lattr: attr; lcp: ctp; lsize: addrrange; lmin,lmax: integer;
- begin
- with fcp^, gattr do
- begin typtr := idtype; kind := varbl;
- case klass of
- vars:
- if vkind = actual then
- begin access := drct; vlevel := vlev;
- dplmt := vaddr
- end
- else
- begin gen2t(54(*lod*),level-vlev,vaddr,nilptr);
- access := indrct; idplmt := 0
- end;
- field:
- with display[disx] do
- if occur = crec then
- begin access := drct; vlevel := clev;
- dplmt := cdspl + fldaddr
- end
- else
- begin
- if level = 1 then gen1t(39(*ldo*),vdspl,nilptr)
- else gen2t(54(*lod*),0,vdspl,nilptr);
- access := indrct; idplmt := fldaddr
- end;
- func:
- if pfdeckind = standard then
- begin error(150); typtr := nil end
- else
- begin
- if pfkind = formal then error(151)
- else
- if (pflev+1<>level)or(fprocp<>fcp) then error(177);
- begin access := drct; vlevel := pflev + 1;
- dplmt := 0 (*impl. relat. addr. of fct. result*)
- end
- end
- end (*case*)
- end (*with*);
- if not (sy in selectsys + fsys) then
- begin error(59); skip(selectsys + fsys) end;
- while sy in selectsys do
- begin
- (*[*) if sy = lbrack then
- begin
- repeat lattr := gattr;
- with lattr do
- if typtr <> nil then
- if typtr^.form <> arrays then
- begin error(138); typtr := nil end;
- loadaddress;
- insymbol; expression(fsys + [comma,rbrack]);
- load;
- if gattr.typtr <> nil then
- if gattr.typtr^.form<>scalar then error(113)
- else if not comptypes(gattr.typtr,intptr) then
- gen0t(58(*ord*),gattr.typtr);
- if lattr.typtr <> nil then
- with lattr.typtr^ do
- begin
- if comptypes(inxtype,gattr.typtr) then
- begin
- if inxtype <> nil then
- begin getbounds(inxtype,lmin,lmax);
- if debug then
- gen2t(45(*chk*),lmin,lmax,intptr);
- if lmin>0 then gen1t(31(*dec*),lmin,intptr)
- else if lmin<0 then
- gen1t(34(*inc*),-lmin,intptr);
- (*or simply gen1(31,lmin)*)
- end
- end
- else error(139);
- with gattr do
- begin typtr := aeltype; kind := varbl;
- access := indrct; idplmt := 0
- end;
- if gattr.typtr <> nil then
- begin
- lsize := gattr.typtr^.size;
- align(gattr.typtr,lsize);
- gen1(36(*ixa*),lsize)
- end
- end
- until sy <> comma;
- if sy = rbrack then insymbol else error(12)
- end (*if sy = lbrack*)
- else
- (*.*) if sy = period then
- begin
- with gattr do
- begin
- if typtr <> nil then
- if typtr^.form <> records then
- begin error(140); typtr := nil end;
- insymbol;
- if sy = ident then
- begin
- if typtr <> nil then
- begin searchsection(typtr^.fstfld,lcp);
- if lcp = nil then
- begin error(152); typtr := nil end
- else
- with lcp^ do
- begin typtr := idtype;
- case access of
- drct: dplmt := dplmt + fldaddr;
- indrct: idplmt := idplmt + fldaddr;
- inxd: error(400)
- end
- end
- end;
- insymbol
- end (*sy = ident*)
- else error(2)
- end (*with gattr*)
- end (*if sy = period*)
- else
- (*^*) begin
- if gattr.typtr <> nil then
- with gattr,typtr^ do
- if form = pointer then
- begin load; typtr := eltype;
- if debug then gen2t(45(*chk*),1,maxaddr,nilptr);
- with gattr do
- begin kind := varbl; access := indrct;
- idplmt := 0
- end
- end
- else
- if form = files then typtr := filtype
- else error(141);
- insymbol
- end;
- if not (sy in fsys + selectsys) then
- begin error(6); skip(fsys + selectsys) end
- end (*while*)
- end (*selector*) ;
-
- procedure call(fsys: setofsys; fcp: ctp);
- var lkey: 1..15;
-
- procedure variable(fsys: setofsys);
- var lcp: ctp;
- begin
- if sy = ident then
- begin searchid([vars,field],lcp); insymbol end
- else begin error(2); lcp := uvarptr end;
- selector(fsys,lcp)
- end (*variable*) ;
-
- procedure getputresetrewrite;
- begin variable(fsys + [rparent]); loadaddress;
- if gattr.typtr <> nil then
- if gattr.typtr^.form <> files then error(116);
- if lkey <= 2 then gen1(30(*csp*),lkey(*get,put*))
- else error(399)
- end (*getputresetrewrite*) ;
-
- procedure read;
- var llev:levrange; laddr:addrrange;
- lsp : stp;
- begin
- llev := 1; laddr := lcaftermarkstack;
- if sy = lparent then
- begin insymbol;
- variable(fsys + [comma,rparent]);
- lsp := gattr.typtr; test := false;
- if lsp <> nil then
- if lsp^.form = files then
- with gattr, lsp^ do
- begin
- if filtype = charptr then
- begin llev := vlevel; laddr := dplmt end
- else error(399);
- if sy = rparent then
- begin if lkey = 5 then error(116);
- test := true
- end
- else
- if sy <> comma then
- begin error(116); skip(fsys + [comma,rparent]) end;
- if sy = comma then
- begin insymbol; variable(fsys + [comma,rparent])
- end
- else test := true
- end;
- if not test then
- repeat loadaddress;
- gen2(50(*lda*),level-llev,laddr);
- if gattr.typtr <> nil then
- if gattr.typtr^.form <= subrange then
- if comptypes(intptr,gattr.typtr) then
- gen1(30(*csp*),3(*rdi*))
- else
- if comptypes(realptr,gattr.typtr) then
- gen1(30(*csp*),4(*rdr*))
- else
- if comptypes(charptr,gattr.typtr) then
- gen1(30(*csp*),5(*rdc*))
- else error(399)
- else error(116);
- test := sy <> comma;
- if not test then
- begin insymbol; variable(fsys + [comma,rparent])
- end
- until test;
- if sy = rparent then insymbol else error(4)
- end
- else if lkey = 5 then error(116);
- if lkey = 11 then
- begin gen2(50(*lda*),level-llev,laddr);
- gen1(30(*csp*),21(*rln*))
- end
- end (*read*) ;
-
- procedure write;
- var lsp: stp; default : boolean; llkey: 1..15;
- llev:levrange; laddr,len:addrrange;
- begin llkey := lkey;
- llev := 1; laddr := lcaftermarkstack + charmax;
- if sy = lparent then
- begin insymbol;
- expression(fsys + [comma,colon,rparent]);
- lsp := gattr.typtr; test := false;
- if lsp <> nil then
- if lsp^.form = files then
- with gattr, lsp^ do
- begin
- if filtype = charptr then
- begin llev := vlevel; laddr := dplmt end
- else error(399);
- if sy = rparent then
- begin if llkey = 6 then error(116);
- test := true
- end
- else
- if sy <> comma then
- begin error(116); skip(fsys+[comma,rparent]) end;
- if sy = comma then
- begin insymbol; expression(fsys+[comma,colon,rparent])
- end
- else test := true
- end;
- if not test then
- repeat
- lsp := gattr.typtr;
- if lsp <> nil then
- if lsp^.form <= subrange then load else loadaddress;
- if sy = colon then
- begin insymbol; expression(fsys + [comma,colon,rparent]);
- if gattr.typtr <> nil then
- if gattr.typtr <> intptr then error(116);
- load; default := false
- end
- else default := true;
- if sy = colon then
- begin insymbol; expression(fsys + [comma,rparent]);
- if gattr.typtr <> nil then
- if gattr.typtr <> intptr then error(116);
- if lsp <> realptr then error(124);
- load; error(399);
- end
- else
- if lsp = intptr then
- begin if default then gen2(51(*ldc*),1,10);
- gen2(50(*lda*),level-llev,laddr);
- gen1(30(*csp*),6(*wri*))
- end
- else
- if lsp = realptr then
- begin if default then gen2(51(*ldc*),1,20);
- gen2(50(*lda*),level-llev,laddr);
- gen1(30(*csp*),8(*wrr*))
- end
- else
- if lsp = charptr then
- begin if default then gen2(51(*ldc*),1,1);
- gen2(50(*lda*),level-llev,laddr);
- gen1(30(*csp*),9(*wrc*))
- end
- else
- if lsp <> nil then
- begin
- if lsp^.form = scalar then error(399)
- else
- if string(lsp) then
- begin len := lsp^.size div charmax;
- if default then
- gen2(51(*ldc*),1,len);
- gen2(51(*ldc*),1,len);
- gen2(50(*lda*),level-llev,laddr);
- gen1(30(*csp*),10(*wrs*))
- end
- else error(116)
- end;
- test := sy <> comma;
- if not test then
- begin insymbol; expression(fsys + [comma,colon,rparent])
- end
- until test;
- if sy = rparent then insymbol else error(4)
- end
- else if lkey = 6 then error(116);
- if llkey = 12 then (*writeln*)
- begin gen2(50(*lda*),level-llev,laddr);
- gen1(30(*csp*),22(*wln*))
- end
- end (*write*) ;
-
- procedure pack;
- var lsp,lsp1: stp;
- begin error(399); variable(fsys + [comma,rparent]);
- lsp := nil; lsp1 := nil;
- if gattr.typtr <> nil then
- with gattr.typtr^ do
- if form = arrays then
- begin lsp := inxtype; lsp1 := aeltype end
- else error(116);
- if sy = comma then insymbol else error(20);
- expression(fsys + [comma,rparent]);
- if gattr.typtr <> nil then
- if gattr.typtr^.form <> scalar then error(116)
- else
- if not comptypes(lsp,gattr.typtr) then error(116);
- if sy = comma then insymbol else error(20);
- variable(fsys + [rparent]);
- if gattr.typtr <> nil then
- with gattr.typtr^ do
- if form = arrays then
- begin
- if not comptypes(aeltype,lsp1)
- or not comptypes(inxtype,lsp) then
- error(116)
- end
- else error(116)
- end (*pack*) ;
-
- procedure unpack;
- var lsp,lsp1: stp;
- begin error(399); variable(fsys + [comma,rparent]);
- lsp := nil; lsp1 := nil;
- if gattr.typtr <> nil then
- with gattr.typtr^ do
- if form = arrays then
- begin lsp := inxtype; lsp1 := aeltype end
- else error(116);
- if sy = comma then insymbol else error(20);
- variable(fsys + [comma,rparent]);
- if gattr.typtr <> nil then
- with gattr.typtr^ do
- if form = arrays then
- begin
- if not comptypes(aeltype,lsp1)
- or not comptypes(inxtype,lsp) then
- error(116)
- end
- else error(116);
- if sy = comma then insymbol else error(20);
- expression(fsys + [rparent]);
- if gattr.typtr <> nil then
- if gattr.typtr^.form <> scalar then error(116)
- else
- if not comptypes(lsp,gattr.typtr) then error(116);
- end (*unpack*) ;
-
- procedure new;
- label 1;
- var lsp,lsp1: stp; varts: integer;
- lsize: addrrange; lval: valu;
- begin variable(fsys + [comma,rparent]); loadaddress;
- lsp := nil; varts := 0; lsize := 0;
- if gattr.typtr <> nil then
- with gattr.typtr^ do
- if form = pointer then
- begin
- if eltype <> nil then
- begin lsize := eltype^.size;
- if eltype^.form = records then lsp := eltype^.recvar
- end
- end
- else error(116);
- while sy = comma do
- begin insymbol;constant(fsys + [comma,rparent],lsp1,lval);
- varts := varts + 1;
- (*check to insert here: is constant in tagfieldtype range*)
- if lsp = nil then error(158)
- else
- if lsp^.form <> tagfld then error(162)
- else
- if lsp^.tagfieldp <> nil then
- if string(lsp1) or (lsp1 = realptr) then error(159)
- else
- if comptypes(lsp^.tagfieldp^.idtype,lsp1) then
- begin
- lsp1 := lsp^.fstvar;
- while lsp1 <> nil do
- with lsp1^ do
- if varval.ival = lval.ival then
- begin lsize := size; lsp := subvar;
- goto 1
- end
- else lsp1 := nxtvar;
- lsize := lsp^.size; lsp := nil;
- end
- else error(116);
- 1: end (*while*) ;
- gen2(51(*ldc*),1,lsize);
- gen1(30(*csp*),12(*new*));
- end (*new*) ;
-
- procedure mark;
- begin variable(fsys+[rparent]);
- if gattr.typtr <> nil then
- if gattr.typtr^.form = pointer then
- begin loadaddress; gen1(30(*csp*),23(*sav*)) end
- else error(116)
- end(*mark*);
-
- procedure release;
- begin variable(fsys+[rparent]);
- if gattr.typtr <> nil then
- if gattr.typtr^.form = pointer then
- begin load; gen1(30(*csp*),13(*rst*)) end
- else error(116)
- end (*release*);
-
-
-
- procedure abs;
- begin
- if gattr.typtr <> nil then
- if gattr.typtr = intptr then gen0(0(*abi*))
- else
- if gattr.typtr = realptr then gen0(1(*abr*))
- else begin error(125); gattr.typtr := intptr end
- end (*abs*) ;
-
- procedure sqr;
- begin
- if gattr.typtr <> nil then
- if gattr.typtr = intptr then gen0(24(*sqi*))
- else
- if gattr.typtr = realptr then gen0(25(*sqr*))
- else begin error(125); gattr.typtr := intptr end
- end (*sqr*) ;
-
- procedure trunc;
- begin
- if gattr.typtr <> nil then
- if gattr.typtr <> realptr then error(125);
- gen0(27(*trc*));
- gattr.typtr := intptr
- end (*trunc*) ;
-
- procedure odd;
- begin
- if gattr.typtr <> nil then
- if gattr.typtr <> intptr then error(125);
- gen0(20(*odd*));
- gattr.typtr := boolptr
- end (*odd*) ;
-
- procedure ord;
- begin
- if gattr.typtr <> nil then
- if gattr.typtr^.form >= power then error(125);
- gen0t(58(*ord*),gattr.typtr);
- gattr.typtr := intptr
- end (*ord*) ;
-
- procedure chr;
- begin
- if gattr.typtr <> nil then
- if gattr.typtr <> intptr then error(125);
- gen0(59(*chr*));
- gattr.typtr := charptr
- end (*chr*) ;
-
- procedure predsucc;
- begin
- if gattr.typtr <> nil then
- if gattr.typtr^.form <> scalar then error(125);
- if lkey = 7 then gen1t(31(*dec*),1,gattr.typtr)
- else gen1t(34(*inc*),1,gattr.typtr)
- end (*predsucc*) ;
-
- procedure eof;
- begin
- if sy = lparent then
- begin insymbol; variable(fsys + [rparent]);
- if sy = rparent then insymbol else error(4)
- end
- else
- with gattr do
- begin typtr := textptr; kind := varbl; access := drct;
- vlevel := 1; dplmt := lcaftermarkstack
- end;
- loadaddress;
- if gattr.typtr <> nil then
- if gattr.typtr^.form <> files then error(125);
- if lkey = 9 then gen0(8(*eof*)) else gen1(30(*csp*),14(*eln*));
- gattr.typtr := boolptr
- end (*eof*) ;
-
-
-
- procedure callnonstandard;
- var nxt,lcp: ctp; lsp: stp; lkind: idkind; lb: boolean;
- locpar, llc: addrrange;
- begin locpar := 0;
- with fcp^ do
- begin nxt := next; lkind := pfkind;
- if not externl then gen1(41(*mst*),level-pflev)
- end;
- if sy = lparent then
- begin llc := lc;
- repeat lb := false; (*decide whether proc/func must be passed*)
- if lkind = actual then
- begin
- if nxt = nil then error(126)
- else lb := nxt^.klass in [proc,func]
- end else error(399);
- (*For formal proc/func, lb is false and expression
- will be called, which will always interpret a proc/func id
- at its beginning as a call rather than a parameter passing.
- In this implementation, parameter procedures/functions
- are therefore not allowed to have procedure/function
- parameters*)
- insymbol;
- if lb then (*pass function or procedure*)
- begin error(399);
- if sy <> ident then
- begin error(2); skip(fsys + [comma,rparent]) end
- else
- begin
- if nxt^.klass = proc then searchid([proc],lcp)
- else
- begin searchid([func],lcp);
- if not comptypes(lcp^.idtype,nxt^.idtype) then
- error(128)
- end;
- insymbol;
- if not (sy in fsys + [comma,rparent]) then
- begin error(6); skip(fsys + [comma,rparent]) end
- end
- end (*if lb*)
- else
- begin expression(fsys + [comma,rparent]);
- if gattr.typtr <> nil then
- if lkind = actual then
- begin
- if nxt <> nil then
- begin lsp := nxt^.idtype;
- if lsp <> nil then
- begin
- if (nxt^.vkind = actual) then
- if lsp^.form <= power then
- begin load;
- if debug then checkbnds(lsp);
- if comptypes(realptr,lsp)
- and (gattr.typtr = intptr) then
- begin gen0(10(*flt*));
- gattr.typtr := realptr
- end;
- locpar := locpar+lsp^.size;
- align(parmptr,locpar);
- end
- else
- begin
- loadaddress;
- locpar := locpar+ptrsize;
- align(parmptr,locpar)
- end
- else
- if gattr.kind = varbl then
- begin loadaddress;
- locpar := locpar+ptrsize;
- align(parmptr,locpar);
- end
- else error(154);
- if not comptypes(lsp,gattr.typtr) then
- error(142)
- end
- end
- end
- else (*lkind = formal*)
- begin (*pass formal param*)
- end
- end;
- if (lkind = actual) and (nxt <> nil) then nxt := nxt^.next
- until sy <> comma;
- lc := llc;
- if sy = rparent then insymbol else error(4)
- end (*if lparent*);
- if lkind = actual then
- begin if nxt <> nil then error(126);
- with fcp^ do
- begin
- if externl then gen1(30(*csp*),pfname)
- else gencupent(46(*cup*),locpar,pfname);
- end
- end;
- gattr.typtr := fcp^.idtype
- end (*callnonstandard*) ;
-
- begin (*call*)
- if fcp^.pfdeckind = standard then
- begin lkey := fcp^.key;
- if fcp^.klass = proc then
- begin
- if not(lkey in [5,6,11,12]) then
- if sy = lparent then insymbol else error(9);
- case lkey of
- 1,2,
- 3,4: getputresetrewrite;
- 5,11: read;
- 6,12: write;
- 7: pack;
- 8: unpack;
- 9: new;
- 10: release;
- 13: mark
- end;
- if not(lkey in [5,6,11,12]) then
- if sy = rparent then insymbol else error(4)
- end
- else
- begin
- if lkey <= 8 then
- begin
- if sy = lparent then insymbol else error(9);
- expression(fsys+[rparent]); load
- end;
- case lkey of
- 1: abs;
- 2: sqr;
- 3: trunc;
- 4: odd;
- 5: ord;
- 6: chr;
- 7,8: predsucc;
- 9,10: eof
- end;
- if lkey <= 8 then
- if sy = rparent then insymbol else error(4)
- end;
- end (*standard procedures and functions*)
- else callnonstandard
- end (*call*) ;
-
- procedure expression;
- var lattr: attr; lop: operator; typind: char; lsize: addrrange;
-
- procedure simpleexpression(fsys: setofsys);
- var lattr: attr; lop: operator; signed: boolean;
-
- procedure term(fsys: setofsys);
- var lattr: attr; lop: operator;
-
- procedure factor(fsys: setofsys);
- var lcp: ctp; lvp: csp; varpart: boolean;
- cstpart: setty; lsp: stp;
- begin
- if not (sy in facbegsys) then
- begin error(58); skip(fsys + facbegsys);
- gattr.typtr := nil
- end;
- while sy in facbegsys do
- begin
- case sy of
- (*id*) ident:
- begin searchid([konst,vars,field,func],lcp);
- insymbol;
- if lcp^.klass = func then
- begin call(fsys,lcp);
- with gattr do
- begin kind := expr;
- if typtr <> nil then
- if typtr^.form=subrange then
- typtr := typtr^.rangetype
- end
- end
- else
- if lcp^.klass = konst then
- with gattr, lcp^ do
- begin typtr := idtype; kind := cst;
- cval := values
- end
- else
- begin selector(fsys,lcp);
- if gattr.typtr<>nil then(*elim.subr.types to*)
- with gattr,typtr^ do(*simplify later tests*)
- if form = subrange then
- typtr := rangetype
- end
- end;
- (*cst*) intconst:
- begin
- with gattr do
- begin typtr := intptr; kind := cst;
- cval := val
- end;
- insymbol
- end;
- realconst:
- begin
- with gattr do
- begin typtr := realptr; kind := cst;
- cval := val
- end;
- insymbol
- end;
- stringconst:
- begin
- with gattr do
- begin
- if lgth = 1 then typtr := charptr
- else
- begin new(lsp,arrays);
- with lsp^ do
- begin aeltype := charptr; form:=arrays;
- inxtype := nil; size := lgth*charsize
- end;
- typtr := lsp
- end;
- kind := cst; cval := val
- end;
- insymbol
- end;
- (* ( *) lparent:
- begin insymbol; expression(fsys + [rparent]);
- if sy = rparent then insymbol else error(4)
- end;
- (*not*) notsy:
- begin insymbol; factor(fsys);
- load; gen0(19(*not*));
- if gattr.typtr <> nil then
- if gattr.typtr <> boolptr then
- begin error(135); gattr.typtr := nil end;
- end;
- (*[*) lbrack:
- begin insymbol; cstpart := [ ]; varpart := false;
- new(lsp,power);
- with lsp^ do
- begin elset:=nil;size:=setsize;form:=power end;
- if sy = rbrack then
- begin
- with gattr do
- begin typtr := lsp; kind := cst end;
- insymbol
- end
- else
- begin
- repeat expression(fsys + [comma,rbrack]);
- if gattr.typtr <> nil then
- if gattr.typtr^.form <> scalar then
- begin error(136); gattr.typtr := nil end
- else
- if comptypes(lsp^.elset,gattr.typtr) then
- begin
- if gattr.kind = cst then
- if (gattr.cval.ival < setlow) or
- (gattr.cval.ival > sethigh) then
- error(304)
- else
- cstpart := cstpart+[gattr.cval.ival]
- else
- begin load;
- if not comptypes(gattr.typtr,intptr)
- then gen0t(58(*ord*),gattr.typtr);
- gen0(23(*sgs*));
- if varpart then gen0(28(*uni*))
- else varpart := true
- end;
- lsp^.elset := gattr.typtr;
- gattr.typtr := lsp
- end
- else error(137);
- test := sy <> comma;
- if not test then insymbol
- until test;
- if sy = rbrack then insymbol else error(12)
- end;
- if varpart then
- begin
- if cstpart <> [ ] then
- begin new(lvp,pset); lvp^.pval := cstpart;
- lvp^.cclass := pset;
- if cstptrix = cstoccmax then error(254)
- else
- begin cstptrix := cstptrix + 1;
- cstptr[cstptrix] := lvp;
- gen2(51(*ldc*),5,cstptrix);
- gen0(28(*uni*)); gattr.kind := expr
- end
- end
- end
- else
- begin new(lvp,pset); lvp^.pval := cstpart;
- lvp^.cclass := pset;
- gattr.cval.valp := lvp
- end
- end
- end (*case*) ;
- if not (sy in fsys) then
- begin error(6); skip(fsys + facbegsys) end
- end (*while*)
- end (*factor*) ;
-
- begin (*term*)
- factor(fsys + [mulop]);
- while sy = mulop do
- begin load; lattr := gattr; lop := op;
- insymbol; factor(fsys + [mulop]); load;
- if (lattr.typtr <> nil) and (gattr.typtr <> nil) then
- case lop of
- (***) mul: if (lattr.typtr=intptr)and(gattr.typtr=intptr)
- then gen0(15(*mpi*))
- else
- begin
- if lattr.typtr = intptr then
- begin gen0(9(*flo*));
- lattr.typtr := realptr
- end
- else
- if gattr.typtr = intptr then
- begin gen0(10(*flt*));
- gattr.typtr := realptr
- end;
- if (lattr.typtr = realptr)
- and(gattr.typtr=realptr)then gen0(16(*mpr*))
- else
- if(lattr.typtr^.form=power)
- and comptypes(lattr.typtr,gattr.typtr)then
- gen0(12(*int*))
- else begin error(134); gattr.typtr:=nil end
- end;
- (* / *) rdiv: begin
- if gattr.typtr = intptr then
- begin gen0(10(*flt*));
- gattr.typtr := realptr
- end;
- if lattr.typtr = intptr then
- begin gen0(9(*flo*));
- lattr.typtr := realptr
- end;
- if (lattr.typtr = realptr)
- and (gattr.typtr=realptr)then gen0(7(*dvr*))
- else begin error(134); gattr.typtr := nil end
- end;
- (*div*) idiv: if (lattr.typtr = intptr)
- and (gattr.typtr = intptr) then gen0(6(*dvi*))
- else begin error(134); gattr.typtr := nil end;
- (*mod*) imod: if (lattr.typtr = intptr)
- and (gattr.typtr = intptr) then gen0(14(*mod*))
- else begin error(134); gattr.typtr := nil end;
- (*and*) andop:if (lattr.typtr = boolptr)
- and (gattr.typtr = boolptr) then gen0(4(*and*))
- else begin error(134); gattr.typtr := nil end
- end (*case*)
- else gattr.typtr := nil
- end (*while*)
- end (*term*) ;
-
- begin (*simpleexpression*)
- signed := false;
- if (sy = addop) and (op in [plus,minus]) then
- begin signed := op = minus; insymbol end;
- term(fsys + [addop]);
- if signed then
- begin load;
- if gattr.typtr = intptr then gen0(17(*ngi*))
- else
- if gattr.typtr = realptr then gen0(18(*ngr*))
- else begin error(134); gattr.typtr := nil end
- end;
- while sy = addop do
- begin load; lattr := gattr; lop := op;
- insymbol; term(fsys + [addop]); load;
- if (lattr.typtr <> nil) and (gattr.typtr <> nil) then
- case lop of
- (*+*) plus:
- if (lattr.typtr = intptr)and(gattr.typtr = intptr) then
- gen0(2(*adi*))
- else
- begin
- if lattr.typtr = intptr then
- begin gen0(9(*flo*));
- lattr.typtr := realptr
- end
- else
- if gattr.typtr = intptr then
- begin gen0(10(*flt*));
- gattr.typtr := realptr
- end;
- if (lattr.typtr = realptr)and(gattr.typtr = realptr)
- then gen0(3(*adr*))
- else if(lattr.typtr^.form=power)
- and comptypes(lattr.typtr,gattr.typtr) then
- gen0(28(*uni*))
- else begin error(134); gattr.typtr:=nil end
- end;
- (*-*) minus:
- if (lattr.typtr = intptr)and(gattr.typtr = intptr) then
- gen0(21(*sbi*))
- else
- begin
- if lattr.typtr = intptr then
- begin gen0(9(*flo*));
- lattr.typtr := realptr
- end
- else
- if gattr.typtr = intptr then
- begin gen0(10(*flt*));
- gattr.typtr := realptr
- end;
- if (lattr.typtr = realptr)and(gattr.typtr = realptr)
- then gen0(22(*sbr*))
- else
- if (lattr.typtr^.form = power)
- and comptypes(lattr.typtr,gattr.typtr) then
- gen0(5(*dif*))
- else begin error(134); gattr.typtr := nil end
- end;
- (*or*) orop:
- if(lattr.typtr=boolptr)and(gattr.typtr=boolptr)then
- gen0(13(*ior*))
- else begin error(134); gattr.typtr := nil end
- end (*case*)
- else gattr.typtr := nil
- end (*while*)
- end (*simpleexpression*) ;
-
- begin (*expression*)
- simpleexpression(fsys + [relop]);
- if sy = relop then
- begin
- if gattr.typtr <> nil then
- if gattr.typtr^.form <= power then load
- else loadaddress;
- lattr := gattr; lop := op;
- if lop = inop then
- if not comptypes(gattr.typtr,intptr) then
- gen0t(58(*ord*),gattr.typtr);
- insymbol; simpleexpression(fsys);
- if gattr.typtr <> nil then
- if gattr.typtr^.form <= power then load
- else loadaddress;
- if (lattr.typtr <> nil) and (gattr.typtr <> nil) then
- if lop = inop then
- if gattr.typtr^.form = power then
- if comptypes(lattr.typtr,gattr.typtr^.elset) then
- gen0(11(*inn*))
- else begin error(129); gattr.typtr := nil end
- else begin error(130); gattr.typtr := nil end
- else
- begin
- if lattr.typtr <> gattr.typtr then
- if lattr.typtr = intptr then
- begin gen0(9(*flo*));
- lattr.typtr := realptr
- end
- else
- if gattr.typtr = intptr then
- begin gen0(10(*flt*));
- gattr.typtr := realptr
- end;
- if comptypes(lattr.typtr,gattr.typtr) then
- begin lsize := lattr.typtr^.size;
- case lattr.typtr^.form of
- scalar:
- if lattr.typtr = realptr then typind := 'r'
- else
- if lattr.typtr = boolptr then typind := 'b'
- else
- if lattr.typtr = charptr then typind := 'c'
- else typind := 'i';
- pointer:
- begin
- if lop in [ltop,leop,gtop,geop] then error(131);
- typind := 'a'
- end;
- power:
- begin if lop in [ltop,gtop] then error(132);
- typind := 's'
- end;
- arrays:
- begin
- if not string(lattr.typtr)
- then error(134);
- typind := 'm'
- end;
- records:
- begin
- error(134);
- typind := 'm'
- end;
- files:
- begin error(133); typind := 'f' end
- end;
- case lop of
- ltop: gen2(53(*les*),ord(typind),lsize);
- leop: gen2(52(*leq*),ord(typind),lsize);
- gtop: gen2(49(*grt*),ord(typind),lsize);
- geop: gen2(48(*geq*),ord(typind),lsize);
- neop: gen2(55(*neq*),ord(typind),lsize);
- eqop: gen2(47(*equ*),ord(typind),lsize)
- end
- end
- else error(129)
- end;
- gattr.typtr := boolptr; gattr.kind := expr
- end (*sy = relop*)
- end (*expression*) ;
-
- procedure assignment(fcp: ctp);
- var lattr: attr;
- begin selector(fsys + [becomes],fcp);
- if sy = becomes then
- begin
- if gattr.typtr <> nil then
- if (gattr.access<>drct) or (gattr.typtr^.form>power) then
- loadaddress;
- lattr := gattr;
- insymbol; expression(fsys);
- if gattr.typtr <> nil then
- if gattr.typtr^.form <= power then load
- else loadaddress;
- if (lattr.typtr <> nil) and (gattr.typtr <> nil) then
- begin
- if comptypes(realptr,lattr.typtr)and(gattr.typtr=intptr)then
- begin gen0(10(*flt*));
- gattr.typtr := realptr
- end;
- if comptypes(lattr.typtr,gattr.typtr) then
- case lattr.typtr^.form of
- scalar,
- subrange: begin
- if debug then checkbnds(lattr.typtr);
- store(lattr)
- end;
- pointer: begin
- if debug then
- gen2t(45(*chk*),0,maxaddr,nilptr);
- store(lattr)
- end;
- power: store(lattr);
- arrays,
- records: gen1(40(*mov*),lattr.typtr^.size);
- files: error(146)
- end
- else error(129)
- end
- end (*sy = becomes*)
- else error(51)
- end (*assignment*) ;
-
- procedure gotostatement;
- var llp: lbp; found: boolean; ttop,ttop1: disprange;
- begin
- if sy = intconst then
- begin
- found := false;
- ttop := top;
- while display[ttop].occur <> blck do ttop := ttop - 1;
- ttop1 := ttop;
- repeat
- llp := display[ttop].flabel;
- while (llp <> nil) and not found do
- with llp^ do
- if labval = val.ival then
- begin found := true;
- if ttop = ttop1 then
- genujpxjp(57(*ujp*),labname)
- else (*goto leads out of procedure*) error(399)
- end
- else llp := nextlab;
- ttop := ttop - 1
- until found or (ttop = 0);
- if not found then error(167);
- insymbol
- end
- else error(15)
- end (*gotostatement*) ;
-
- procedure compoundstatement;
- begin
- repeat
- repeat statement(fsys + [semicolon,endsy])
- until not (sy in statbegsys);
- test := sy <> semicolon;
- if not test then insymbol
- until test;
- if sy = endsy then insymbol else error(13)
- end (*compoundstatemenet*) ;
-
- procedure ifstatement;
- var lcix1,lcix2: integer;
- begin expression(fsys + [thensy]);
- genlabel(lcix1); genfjp(lcix1);
- if sy = thensy then insymbol else error(52);
- statement(fsys + [elsesy]);
- if sy = elsesy then
- begin genlabel(lcix2); genujpxjp(57(*ujp*),lcix2);
- putlabel(lcix1);
- insymbol; statement(fsys);
- putlabel(lcix2)
- end
- else putlabel(lcix1)
- end (*ifstatement*) ;
-
- procedure casestatement;
- label 1;
- type cip = ^caseinfo;
- caseinfo = packed
- record next: cip;
- csstart: integer;
- cslab: integer
- end;
- var lsp,lsp1: stp; fstptr,lpt1,lpt2,lpt3: cip; lval: valu;
- laddr, lcix, lcix1, lmin, lmax: integer;
- begin expression(fsys + [ofsy,comma,colon]);
- load; genlabel(lcix);
- lsp := gattr.typtr;
- if lsp <> nil then
- if (lsp^.form <> scalar) or (lsp = realptr) then
- begin error(144); lsp := nil end
- else if not comptypes(lsp,intptr) then gen0t(58(*ord*),lsp);
- genujpxjp(57(*ujp*),lcix);
- if sy = ofsy then insymbol else error(8);
- fstptr := nil; genlabel(laddr);
- repeat
- lpt3 := nil; genlabel(lcix1);
- if not(sy in [semicolon,endsy]) then
- begin
- repeat constant(fsys + [comma,colon],lsp1,lval);
- if lsp <> nil then
- if comptypes(lsp,lsp1) then
- begin lpt1 := fstptr; lpt2 := nil;
- while lpt1 <> nil do
- with lpt1^ do
- begin
- if cslab <= lval.ival then
- begin if cslab = lval.ival then error(156);
- goto 1
- end;
- lpt2 := lpt1; lpt1 := next
- end;
- 1: new(lpt3);
- with lpt3^ do
- begin next := lpt1; cslab := lval.ival;
- csstart := lcix1
- end;
- if lpt2 = nil then fstptr := lpt3
- else lpt2^.next := lpt3
- end
- else error(147);
- test := sy <> comma;
- if not test then insymbol
- until test;
- if sy = colon then insymbol else error(5);
- putlabel(lcix1);
- repeat statement(fsys + [semicolon])
- until not (sy in statbegsys);
- if lpt3 <> nil then
- genujpxjp(57(*ujp*),laddr);
- end;
- test := sy <> semicolon;
- if not test then insymbol
- until test;
- putlabel(lcix);
- if fstptr <> nil then
- begin lmax := fstptr^.cslab;
- (*reverse pointers*)
- lpt1 := fstptr; fstptr := nil;
- repeat lpt2 := lpt1^.next; lpt1^.next := fstptr;
- fstptr := lpt1; lpt1 := lpt2
- until lpt1 = nil;
- lmin := fstptr^.cslab;
- if lmax - lmin < cixmax then
- begin
- gen2t(45(*chk*),lmin,lmax,intptr);
- gen2(51(*ldc*),1,lmin); gen0(21(*sbi*)); genlabel(lcix);
- genujpxjp(44(*xjp*),lcix); putlabel(lcix);
- repeat
- with fstptr^ do
- begin
- while cslab > lmin do
- begin gen0(60(*ujc error*));
- lmin := lmin+1
- end;
- genujpxjp(57(*ujp*),csstart);
- fstptr := next; lmin := lmin + 1
- end
- until fstptr = nil;
- putlabel(laddr)
- end
- else error(157)
- end;
- if sy = endsy then insymbol else error(13)
- end (*casestatement*) ;
-
- procedure repeatstatement;
- var laddr: integer;
- begin genlabel(laddr); putlabel(laddr);
- repeat statement(fsys + [semicolon,untilsy]);
- if sy in statbegsys then error(14)
- until not(sy in statbegsys);
- while sy = semicolon do
- begin insymbol;
- repeat statement(fsys + [semicolon,untilsy]);
- if sy in statbegsys then error(14)
- until not (sy in statbegsys);
- end;
- if sy = untilsy then
- begin insymbol; expression(fsys); genfjp(laddr)
- end
- else error(53)
- end (*repeatstatement*) ;
-
- procedure whilestatement;
- var laddr, lcix: integer;
- begin genlabel(laddr); putlabel(laddr);
- expression(fsys + [dosy]); genlabel(lcix); genfjp(lcix);
- if sy = dosy then insymbol else error(54);
- statement(fsys); genujpxjp(57(*ujp*),laddr); putlabel(lcix)
- end (*whilestatement*) ;
-
- procedure forstatement;
- var lattr: attr; lsy: symbol;
- lcix, laddr: integer;
- llc: addrrange;
- begin llc := lc;
- with lattr do
- begin typtr := nil; kind := varbl;
- access := drct; vlevel := level; dplmt := 0
- end;
- if sy = ident then
- begin searchid([vars],lcp);
- with lcp^, lattr do
- begin typtr := idtype; kind := varbl;
- if vkind = actual then
- begin access := drct; vlevel := vlev;
- dplmt := vaddr
- end
- else begin error(155); typtr := nil end
- end;
- if lattr.typtr <> nil then
- if (lattr.typtr^.form > subrange)
- or comptypes(realptr,lattr.typtr) then
- begin error(143); lattr.typtr := nil end;
- insymbol
- end
- else
- begin error(2); skip(fsys + [becomes,tosy,downtosy,dosy]) end;
- if sy = becomes then
- begin insymbol; expression(fsys + [tosy,downtosy,dosy]);
- if gattr.typtr <> nil then
- if gattr.typtr^.form <> scalar then error(144)
- else
- if comptypes(lattr.typtr,gattr.typtr) then
- begin load; store(lattr) end
- else error(145)
- end
- else
- begin error(51); skip(fsys + [tosy,downtosy,dosy]) end;
- if sy in [tosy,downtosy] then
- begin lsy := sy; insymbol; expression(fsys + [dosy]);
- if gattr.typtr <> nil then
- if gattr.typtr^.form <> scalar then error(144)
- else
- if comptypes(lattr.typtr,gattr.typtr) then
- begin load;
- if not comptypes(lattr.typtr,intptr) then
- gen0t(58(*ord*),gattr.typtr);
- align(intptr,lc);
- gen2t(56(*str*),0,lc,intptr);
- genlabel(laddr); putlabel(laddr);
- gattr := lattr; load;
- if not comptypes(gattr.typtr,intptr) then
- gen0t(58(*ord*),gattr.typtr);
- gen2t(54(*lod*),0,lc,intptr);
- lc := lc + intsize;
- if lc > lcmax then lcmax := lc;
- if lsy = tosy then gen2(52(*leq*),ord('i'),1)
- else gen2(48(*geq*),ord('i'),1);
- end
- else error(145)
- end
- else begin error(55); skip(fsys + [dosy]) end;
- genlabel(lcix); genujpxjp(33(*fjp*),lcix);
- if sy = dosy then insymbol else error(54);
- statement(fsys);
- gattr := lattr; load;
- if lsy=tosy then gen1t(34(*inc*),1,gattr.typtr)
- else gen1t(31(*dec*),1,gattr.typtr);
- store(lattr); genujpxjp(57(*ujp*),laddr); putlabel(lcix);
- lc := llc;
- end (*forstatement*) ;
-
-
- procedure withstatement;
- var lcp: ctp; lcnt1: disprange; llc: addrrange;
- begin lcnt1 := 0; llc := lc;
- repeat
- if sy = ident then
- begin searchid([vars,field],lcp); insymbol end
- else begin error(2); lcp := uvarptr end;
- selector(fsys + [comma,dosy],lcp);
- if gattr.typtr <> nil then
- if gattr.typtr^.form = records then
- if top < displimit then
- begin top := top + 1; lcnt1 := lcnt1 + 1;
- with display[top] do
- begin fname := gattr.typtr^.fstfld;
- flabel := nil
- end;
- if gattr.access = drct then
- with display[top] do
- begin occur := crec; clev := gattr.vlevel;
- cdspl := gattr.dplmt
- end
- else
- begin loadaddress;
- align(nilptr,lc);
- gen2t(56(*str*),0,lc,nilptr);
- with display[top] do
- begin occur := vrec; vdspl := lc end;
- lc := lc+ptrsize;
- if lc > lcmax then lcmax := lc
- end
- end
- else error(250)
- else error(140);
- test := sy <> comma;
- if not test then insymbol
- until test;
- if sy = dosy then insymbol else error(54);
- statement(fsys);
- top := top-lcnt1; lc := llc;
- end (*withstatement*) ;
-
- begin (*statement*)
- if sy = intconst then (*label*)
- begin llp := display[level].flabel;
- while llp <> nil do
- with llp^ do
- if labval = val.ival then
- begin if defined then error(165);
- putlabel(labname); defined := true;
- goto 1
- end
- else llp := nextlab;
- error(167);
- 1: insymbol;
- if sy = colon then insymbol else error(5)
- end;
- if not (sy in fsys + [ident]) then
- begin error(6); skip(fsys) end;
- if sy in statbegsys + [ident] then
- begin
- case sy of
- ident: begin searchid([vars,field,func,proc],lcp); insymbol;
- if lcp^.klass = proc then call(fsys,lcp)
- else assignment(lcp)
- end;
- beginsy: begin insymbol; compoundstatement end;
- gotosy: begin insymbol; gotostatement end;
- ifsy: begin insymbol; ifstatement end;
- casesy: begin insymbol; casestatement end;
- whilesy: begin insymbol; whilestatement end;
- repeatsy: begin insymbol; repeatstatement end;
- forsy: begin insymbol; forstatement end;
- withsy: begin insymbol; withstatement end
- end;
- if not (sy in [semicolon,endsy,elsesy,untilsy]) then
- begin error(6); skip(fsys) end
- end
- end (*statement*) ;
-
- begin (*body*)
- if fprocp <> nil then entname := fprocp^.pfname
- else genlabel(entname);
- cstptrix := 0; topnew := lcaftermarkstack; topmax := lcaftermarkstack;
- putlabel(entname); genlabel(segsize); genlabel(stacktop);
- gencupent(32(*ent1*),1,segsize); gencupent(32(*ent2*),2,stacktop);
- if fprocp <> nil then (*copy multiple values into local cells*)
- begin llc1 := lcaftermarkstack;
- lcp := fprocp^.next;
- while lcp <> nil do
- with lcp^ do
- begin
- align(parmptr,llc1);
- if klass = vars then
- if idtype <> nil then
- if idtype^.form > power then
- begin
- if vkind = actual then
- begin
- gen2(50(*lda*),0,vaddr);
- gen2t(54(*lod*),0,llc1,nilptr);
- gen1(40(*mov*),idtype^.size);
- end;
- llc1 := llc1 + ptrsize
- end
- else llc1 := llc1 + idtype^.size;
- lcp := lcp^.next;
- end;
- end;
- lcmax := lc;
- repeat
- repeat statement(fsys + [semicolon,endsy])
- until not (sy in statbegsys);
- test := sy <> semicolon;
- if not test then insymbol
- until test;
- if sy = endsy then insymbol else error(13);
- llp := display[top].flabel; (*test for undefined labels*)
- while llp <> nil do
- with llp^ do
- begin
- if not defined then
- begin error(168);
- writeln(output); writeln(output,' label ',labval);
- write(output,' ':chcnt+16)
- end;
- llp := nextlab
- end;
- if fprocp <> nil then
- begin
- if fprocp^.idtype = nil then gen1(42(*ret*),ord('p'))
- else gen0t(42(*ret*),fprocp^.idtype);
- align(parmptr,lcmax);
- if prcode then
- begin writeln(prr,'l',segsize:4,'=',lcmax);
- writeln(prr,'l',stacktop:4,'=',topmax)
- end
- end
- else
- begin gen1(42(*ret*),ord('p'));
- align(parmptr,lcmax);
- if prcode then
- begin writeln(prr,'l',segsize:4,'=',lcmax);
- writeln(prr,'l',stacktop:4,'=',topmax);
- writeln(prr,'q')
- end;
- ic := 0;
- (*generate call of main program; note that this call must be loaded
- at absolute address zero*)
- gen1(41(*mst*),0); gencupent(46(*cup*),0,entname); gen0(29(*stp*));
- if prcode then
- writeln(prr,'q');
- saveid := id;
- while fextfilep <> nil do
- begin
- with fextfilep^ do
- if not ((filename = 'input ') or (filename = 'output ') or
- (filename = 'prd ') or (filename = 'prr '))
- then begin id := filename;
- searchid([vars],llcp);
- if llcp^.idtype<>nil then
- if llcp^.idtype^.form<>files then
- begin writeln(output);
- writeln(output,' ':8,'undeclared ','external ',
- 'file',fextfilep^.filename:8);
- write(output,' ':chcnt+16)
- end
- end;
- fextfilep := fextfilep^.nextfile
- end;
- id := saveid;
- if prtables then
- begin writeln(output); printtables(true)
- end
- end;
- end (*body*) ;
-
- begin (*block*)
- dp := true;
- repeat
- if sy = labelsy then
- begin insymbol; labeldeclaration end;
- if sy = constsy then
- begin insymbol; constdeclaration end;
- if sy = typesy then
- begin insymbol; typedeclaration end;
- if sy = varsy then
- begin insymbol; vardeclaration end;
- while sy in [procsy,funcsy] do
- begin lsy := sy; insymbol; procdeclaration(lsy) end;
- if sy <> beginsy then
- begin error(18); skip(fsys) end
- until (sy in statbegsys) or eof(input);
- dp := false;
- if sy = beginsy then insymbol else error(17);
- repeat body(fsys + [casesy]);
- if sy <> fsy then
- begin error(6); skip(fsys) end
- until ((sy = fsy) or (sy in blockbegsys)) or eof(input);
- end (*block*) ;
-
- procedure programme(fsys:setofsys);
- var extfp:extfilep;
- begin
- if sy = progsy then
- begin insymbol; if sy <> ident then error(2); insymbol;
- if not (sy in [lparent,semicolon]) then error(14);
- if sy = lparent then
- begin
- repeat insymbol;
- if sy = ident then
- begin new(extfp);
- with extfp^ do
- begin filename := id; nextfile := fextfilep end;
- fextfilep := extfp;
- insymbol;
- if not ( sy in [comma,rparent] ) then error(20)
- end
- else error(2)
- until sy <> comma;
- if sy <> rparent then error(4);
- insymbol
- end;
- if sy <> semicolon then error(14)
- else insymbol;
- end;
- repeat block(fsys,period,nil);
- if sy <> period then error(21)
- until (sy = period) or eof(input);
- if list then writeln(output);
- if errinx <> 0 then
- begin list := false; endofline end
- end (*programme*) ;
-
-
- procedure stdnames;
- begin
- na[ 1] := 'false '; na[ 2] := 'true '; na[ 3] := 'input ';
- na[ 4] := 'output '; na[ 5] := 'get '; na[ 6] := 'put ';
- na[ 7] := 'reset '; na[ 8] := 'rewrite '; na[ 9] := 'read ';
- na[10] := 'write '; na[11] := 'pack '; na[12] := 'unpack ';
- na[13] := 'new '; na[14] := 'release '; na[15] := 'readln ';
- na[16] := 'writeln ';
- na[17] := 'abs '; na[18] := 'sqr '; na[19] := 'trunc ';
- na[20] := 'odd '; na[21] := 'ord '; na[22] := 'chr ';
- na[23] := 'pred '; na[24] := 'succ '; na[25] := 'eof ';
- na[26] := 'eoln ';
- na[27] := 'sin '; na[28] := 'cos '; na[29] := 'exp ';
- na[30] := 'sqrt '; na[31] := 'ln '; na[32] := 'arctan ';
- na[33] := 'prd '; na[34] := 'prr '; na[35] := 'mark ';
- end (*stdnames*) ;
-
- procedure enterstdtypes;
-
- begin (*type underlying:*)
- (******************)
-
- new(intptr,scalar,standard); (*integer*)
- with intptr^ do
- begin size := intsize; form := scalar; scalkind := standard end;
- new(realptr,scalar,standard); (*real*)
- with realptr^ do
- begin size := realsize; form := scalar; scalkind := standard end;
- new(charptr,scalar,standard); (*char*)
- with charptr^ do
- begin size := charsize; form := scalar; scalkind := standard end;
- new(boolptr,scalar,declared); (*boolean*)
- with boolptr^ do
- begin size := boolsize; form := scalar; scalkind := declared end;
- new(nilptr,pointer); (*nil*)
- with nilptr^ do
- begin eltype := nil; size := ptrsize; form := pointer end;
- new(parmptr,scalar,standard); (*for alignment of parameters*)
- with parmptr^ do
- begin size := parmsize; form := scalar; scalkind := standard end ;
- new(textptr,files); (*text*)
- with textptr^ do
- begin filtype := charptr; size := charsize; form := files end
- end (*enterstdtypes*) ;
-
- procedure entstdnames;
- var cp,cp1: ctp; i: integer;
- begin (*name:*)
- (*******)
-
- new(cp,types); (*integer*)
- with cp^ do
- begin name := 'integer '; idtype := intptr; klass := types end;
- enterid(cp);
- new(cp,types); (*real*)
- with cp^ do
- begin name := 'real '; idtype := realptr; klass := types end;
- enterid(cp);
- new(cp,types); (*char*)
- with cp^ do
- begin name := 'char '; idtype := charptr; klass := types end;
- enterid(cp);
- new(cp,types); (*boolean*)
- with cp^ do
- begin name := 'boolean '; idtype := boolptr; klass := types end;
- enterid(cp);
- cp1 := nil;
- for i := 1 to 2 do
- begin new(cp,konst); (*false,true*)
- with cp^ do
- begin name := na[i]; idtype := boolptr;
- next := cp1; values.ival := i - 1; klass := konst
- end;
- enterid(cp); cp1 := cp
- end;
- boolptr^.fconst := cp;
- new(cp,konst); (*nil*)
- with cp^ do
- begin name := 'nil '; idtype := nilptr;
- next := nil; values.ival := 0; klass := konst
- end;
- enterid(cp);
- for i := 3 to 4 do
- begin new(cp,vars); (*input,output*)
- with cp^ do
- begin name := na[i]; idtype := textptr; klass := vars;
- vkind := actual; next := nil; vlev := 1;
- vaddr := lcaftermarkstack+(i-3)*charmax;
- end;
- enterid(cp)
- end;
- for i:=33 to 34 do
- begin new(cp,vars); (*prd,prr files*)
- with cp^ do
- begin name := na[i]; idtype := textptr; klass := vars;
- vkind := actual; next := nil; vlev := 1;
- vaddr := lcaftermarkstack+(i-31)*charmax;
- end;
- enterid(cp)
- end;
- for i := 5 to 16 do
- begin new(cp,proc,standard); (*get,put,reset*)
- with cp^ do (*rewrite,read*)
- begin name := na[i]; idtype := nil; (*write,pack*)
- next := nil; key := i - 4; (*unpack,pack*)
- klass := proc; pfdeckind := standard
- end;
- enterid(cp)
- end;
- new(cp,proc,standard);
- with cp^ do
- begin name:=na[35]; idtype:=nil;
- next:= nil; key:=13;
- klass:=proc; pfdeckind:= standard
- end; enterid(cp);
- for i := 17 to 26 do
- begin new(cp,func,standard); (*abs,sqr,trunc*)
- with cp^ do (*odd,ord,chr*)
- begin name := na[i]; idtype := nil; (*pred,succ,eof*)
- next := nil; key := i - 16;
- klass := func; pfdeckind := standard
- end;
- enterid(cp)
- end;
- new(cp,vars); (*parameter of predeclared functions*)
- with cp^ do
- begin name := ' '; idtype := realptr; klass := vars;
- vkind := actual; next := nil; vlev := 1; vaddr := 0
- end;
- for i := 27 to 32 do
- begin new(cp1,func,declared,actual); (*sin,cos,exp*)
- with cp1^ do (*sqrt,ln,arctan*)
- begin name := na[i]; idtype := realptr; next := cp;
- forwdecl := false; externl := true; pflev := 0; pfname := i - 12;
- klass := func; pfdeckind := declared; pfkind := actual
- end;
- enterid(cp1)
- end
- end (*entstdnames*) ;
-
- procedure enterundecl;
- begin
- new(utypptr,types);
- with utypptr^ do
- begin name := ' '; idtype := nil; klass := types end;
- new(ucstptr,konst);
- with ucstptr^ do
- begin name := ' '; idtype := nil; next := nil;
- values.ival := 0; klass := konst
- end;
- new(uvarptr,vars);
- with uvarptr^ do
- begin name := ' '; idtype := nil; vkind := actual;
- next := nil; vlev := 0; vaddr := 0; klass := vars
- end;
- new(ufldptr,field);
- with ufldptr^ do
- begin name := ' '; idtype := nil; next := nil; fldaddr := 0;
- klass := field
- end;
- new(uprcptr,proc,declared,actual);
- with uprcptr^ do
- begin name := ' '; idtype := nil; forwdecl := false;
- next := nil; externl := false; pflev := 0; genlabel(pfname);
- klass := proc; pfdeckind := declared; pfkind := actual
- end;
- new(ufctptr,func,declared,actual);
- with ufctptr^ do
- begin name := ' '; idtype := nil; next := nil;
- forwdecl := false; externl := false; pflev := 0; genlabel(pfname);
- klass := func; pfdeckind := declared; pfkind := actual
- end
- end (*enterundecl*) ;
-
- procedure initscalars;
- begin fwptr := nil;
- prtables := false; list := true; prcode := true; debug := true;
- dp := true; prterr := true; errinx := 0;
- intlabel := 0; kk := 8; fextfilep := nil;
- lc := lcaftermarkstack+filebuffer*charmax;
- (* note in the above reservation of buffer store for 2 text files *)
- ic := 3; eol := true; linecount := 0;
- ch := ' '; chcnt := 0;
- globtestp := nil;
- mxint10 := maxint div 10; digmax := strglgth - 1;
- end (*initscalars*) ;
-
- procedure initsets;
- begin
- constbegsys := [addop,intconst,realconst,stringconst,ident];
- simptypebegsys := [lparent] + constbegsys;
- typebegsys:=[arrow,packedsy,arraysy,recordsy,setsy,filesy]+simptypebegsys;
- typedels := [arraysy,recordsy,setsy,filesy];
- blockbegsys := [labelsy,constsy,typesy,varsy,procsy,funcsy,beginsy];
- selectsys := [arrow,period,lbrack];
- facbegsys := [intconst,realconst,stringconst,ident,lparent,lbrack,notsy];
- statbegsys := [beginsy,gotosy,ifsy,whilesy,repeatsy,forsy,withsy,casesy];
- end (*initsets*) ;
-
- procedure inittables;
- procedure reswords;
- begin
- rw[ 1] := 'if '; rw[ 2] := 'do '; rw[ 3] := 'of ';
- rw[ 4] := 'to '; rw[ 5] := 'in '; rw[ 6] := 'or ';
- rw[ 7] := 'end '; rw[ 8] := 'for '; rw[ 9] := 'var ';
- rw[10] := 'div '; rw[11] := 'mod '; rw[12] := 'set ';
- rw[13] := 'and '; rw[14] := 'not '; rw[15] := 'then ';
- rw[16] := 'else '; rw[17] := 'with '; rw[18] := 'goto ';
- rw[19] := 'case '; rw[20] := 'type ';
- rw[21] := 'file '; rw[22] := 'begin ';
- rw[23] := 'until '; rw[24] := 'while '; rw[25] := 'array ';
- rw[26] := 'const '; rw[27] := 'label ';
- rw[28] := 'repeat '; rw[29] := 'record '; rw[30] := 'downto ';
- rw[31] := 'packed '; rw[32] := 'forward '; rw[33] := 'program ';
- rw[34] := 'function'; rw[35] := 'procedur';
- frw[1] := 1; frw[2] := 1; frw[3] := 7; frw[4] := 15; frw[5] := 22;
- frw[6] := 28; frw[7] := 32; frw[8] := 34; frw[9] := 36;
- end (*reswords*) ;
-
- procedure symbols;
- begin
- rsy[ 1] := ifsy; rsy[ 2] := dosy; rsy[ 3] := ofsy;
- rsy[ 4] := tosy; rsy[ 5] := relop; rsy[ 6] := addop;
- rsy[ 7] := endsy; rsy[ 8] := forsy; rsy[ 9] := varsy;
- rsy[10] := mulop; rsy[11] := mulop; rsy[12] := setsy;
- rsy[13] := mulop; rsy[14] := notsy; rsy[15] := thensy;
- rsy[16] := elsesy; rsy[17] := withsy; rsy[18] := gotosy;
- rsy[19] := casesy; rsy[20] := typesy;
- rsy[21] := filesy; rsy[22] := beginsy;
- rsy[23] := untilsy; rsy[24] := whilesy; rsy[25] := arraysy;
- rsy[26] := constsy; rsy[27] := labelsy;
- rsy[28] := repeatsy; rsy[29] := recordsy; rsy[30] := downtosy;
- rsy[31] := packedsy; rsy[32] := forwardsy; rsy[33] := progsy;
- rsy[34] := funcsy; rsy[35] := procsy;
- ssy['+'] := addop ; ssy['-'] := addop; ssy['*'] := mulop;
- ssy['/'] := mulop ; ssy['('] := lparent; ssy[')'] := rparent;
- ssy['$'] := othersy ; ssy['='] := relop; ssy[' '] := othersy;
- ssy[','] := comma ; ssy['.'] := period; ssy['''']:= othersy;
- ssy['['] := lbrack ; ssy[']'] := rbrack; ssy[':'] := colon;
- ssy['^'] := arrow ; ssy['<'] := relop; ssy['>'] := relop;
- ssy[';'] := semicolon;
- end (*symbols*) ;
-
- procedure rators;
- var i: integer;
- begin
- for i := 1 to 35 (*nr of res words*) do rop[i] := noop;
- rop[5] := inop; rop[10] := idiv; rop[11] := imod;
- rop[6] := orop; rop[13] := andop;
- for i := ordminchar to ordmaxchar do sop[chr(i)] := noop;
- sop['+'] := plus; sop['-'] := minus; sop['*'] := mul; sop['/'] := rdiv;
- sop['='] := eqop; sop['<'] := ltop; sop['>'] := gtop;
- end (*rators*) ;
-
- procedure procmnemonics;
- begin
- sna[ 1] :=' get'; sna[ 2] :=' put'; sna[ 3] :=' rdi'; sna[ 4] :=' rdr';
- sna[ 5] :=' rdc'; sna[ 6] :=' wri'; sna[ 7] :=' wro'; sna[ 8] :=' wrr';
- sna[ 9] :=' wrc'; sna[10] :=' wrs'; sna[11] :=' pak'; sna[12] :=' new';
- sna[13] :=' rst'; sna[14] :=' eln'; sna[15] :=' sin'; sna[16] :=' cos';
- sna[17] :=' exp'; sna[18] :=' sqt'; sna[19] :=' log'; sna[20] :=' atn';
- sna[21] :=' rln'; sna[22] :=' wln'; sna[23] :=' sav';
- end (*procmnemonics*) ;
-
- procedure instrmnemonics;
- begin
- mn[ 0] :=' abi'; mn[ 1] :=' abr'; mn[ 2] :=' adi'; mn[ 3] :=' adr';
- mn[ 4] :=' and'; mn[ 5] :=' dif'; mn[ 6] :=' dvi'; mn[ 7] :=' dvr';
- mn[ 8] :=' eof'; mn[ 9] :=' flo'; mn[10] :=' flt'; mn[11] :=' inn';
- mn[12] :=' int'; mn[13] :=' ior'; mn[14] :=' mod'; mn[15] :=' mpi';
- mn[16] :=' mpr'; mn[17] :=' ngi'; mn[18] :=' ngr'; mn[19] :=' not';
- mn[20] :=' odd'; mn[21] :=' sbi'; mn[22] :=' sbr'; mn[23] :=' sgs';
- mn[24] :=' sqi'; mn[25] :=' sqr'; mn[26] :=' sto'; mn[27] :=' trc';
- mn[28] :=' uni'; mn[29] :=' stp'; mn[30] :=' csp'; mn[31] :=' dec';
- mn[32] :=' ent'; mn[33] :=' fjp'; mn[34] :=' inc'; mn[35] :=' ind';
- mn[36] :=' ixa'; mn[37] :=' lao'; mn[38] :=' lca'; mn[39] :=' ldo';
- mn[40] :=' mov'; mn[41] :=' mst'; mn[42] :=' ret'; mn[43] :=' sro';
- mn[44] :=' xjp'; mn[45] :=' chk'; mn[46] :=' cup'; mn[47] :=' equ';
- mn[48] :=' geq'; mn[49] :=' grt'; mn[50] :=' lda'; mn[51] :=' ldc';
- mn[52] :=' leq'; mn[53] :=' les'; mn[54] :=' lod'; mn[55] :=' neq';
- mn[56] :=' str'; mn[57] :=' ujp'; mn[58] :=' ord'; mn[59] :=' chr';
- mn[60] :=' ujc';
- end (*instrmnemonics*) ;
-
- procedure chartypes;
- var i : integer;
- begin
- for i := ordminchar to ordmaxchar do chartp[chr(i)] := illegal;
- chartp['a'] := letter ;
- chartp['b'] := letter ; chartp['c'] := letter ;
- chartp['d'] := letter ; chartp['e'] := letter ;
- chartp['f'] := letter ; chartp['g'] := letter ;
- chartp['h'] := letter ; chartp['i'] := letter ;
- chartp['j'] := letter ; chartp['k'] := letter ;
- chartp['l'] := letter ; chartp['m'] := letter ;
- chartp['n'] := letter ; chartp['o'] := letter ;
- chartp['p'] := letter ; chartp['q'] := letter ;
- chartp['r'] := letter ; chartp['s'] := letter ;
- chartp['t'] := letter ; chartp['u'] := letter ;
- chartp['v'] := letter ; chartp['w'] := letter ;
- chartp['x'] := letter ; chartp['y'] := letter ;
- chartp['z'] := letter ; chartp['0'] := number ;
- chartp['1'] := number ; chartp['2'] := number ;
- chartp['3'] := number ; chartp['4'] := number ;
- chartp['5'] := number ; chartp['6'] := number ;
- chartp['7'] := number ; chartp['8'] := number ;
- chartp['9'] := number ; chartp['+'] := special ;
- chartp['-'] := special ; chartp['*'] := special ;
- chartp['/'] := special ; chartp['('] := chlparen;
- chartp[')'] := special ; chartp['$'] := special ;
- chartp['='] := special ; chartp[' '] := chspace ;
- chartp[','] := special ; chartp['.'] := chperiod;
- chartp['''']:= chstrquo; chartp['['] := special ;
- chartp[']'] := special ; chartp[':'] := chcolon ;
- chartp['^'] := special ; chartp[';'] := special ;
- chartp['<'] := chlt ; chartp['>'] := chgt ;
- ordint['0'] := 0; ordint['1'] := 1; ordint['2'] := 2;
- ordint['3'] := 3; ordint['4'] := 4; ordint['5'] := 5;
- ordint['6'] := 6; ordint['7'] := 7; ordint['8'] := 8;
- ordint['9'] := 9;
- end;
-
- procedure initdx;
- begin
- cdx[ 0] := 0; cdx[ 1] := 0; cdx[ 2] := -1; cdx[ 3] := -1;
- cdx[ 4] := -1; cdx[ 5] := -1; cdx[ 6] := -1; cdx[ 7] := -1;
- cdx[ 8] := 0; cdx[ 9] := 0; cdx[10] := 0; cdx[11] := -1;
- cdx[12] := -1; cdx[13] := -1; cdx[14] := -1; cdx[15] := -1;
- cdx[16] := -1; cdx[17] := 0; cdx[18] := 0; cdx[19] := 0;
- cdx[20] := 0; cdx[21] := -1; cdx[22] := -1; cdx[23] := 0;
- cdx[24] := 0; cdx[25] := 0; cdx[26] := -2; cdx[27] := 0;
- cdx[28] := -1; cdx[29] := 0; cdx[30] := 0; cdx[31] := 0;
- cdx[32] := 0; cdx[33] := -1; cdx[34] := 0; cdx[35] := 0;
- cdx[36] := -1; cdx[37] := +1; cdx[38] := +1; cdx[39] := +1;
- cdx[40] := -2; cdx[41] := 0; cdx[42] := 0; cdx[43] := -1;
- cdx[44] := -1; cdx[45] := 0; cdx[46] := 0; cdx[47] := -1;
- cdx[48] := -1; cdx[49] := -1; cdx[50] := +1; cdx[51] := +1;
- cdx[52] := -1; cdx[53] := -1; cdx[54] := +1; cdx[55] := -1;
- cdx[56] := -1; cdx[57] := 0; cdx[58] := 0; cdx[59] := 0;
- cdx[60] := 0;
- pdx[ 1] := -1; pdx[ 2] := -1; pdx[ 3] := -2; pdx[ 4] := -2;
- pdx[ 5] := -2; pdx[ 6] := -3; pdx[ 7] := -3; pdx[ 8] := -3;
- pdx[ 9] := -3; pdx[10] := -4; pdx[11] := 0; pdx[12] := -2;
- pdx[13] := -1; pdx[14] := 0; pdx[15] := 0; pdx[16] := 0;
- pdx[17] := 0; pdx[18] := 0; pdx[19] := 0; pdx[20] := 0;
- pdx[21] := -1; pdx[22] := -1; pdx[23] := -1;
- end;
-
- begin (*inittables*)
- reswords; symbols; rators;
- instrmnemonics; procmnemonics;
- chartypes; initdx;
- end (*inittables*) ;
-
- begin
- (*initialize*)
- (************)
- initscalars; initsets; inittables;
-
-
- (*enter standard names and standard types:*)
- (******************************************)
- level := 0; top := 0;
- with display[0] do
- begin fname := nil; flabel := nil; occur := blck end;
- enterstdtypes; stdnames; entstdnames; enterundecl;
- top := 1; level := 1;
- with display[1] do
- begin fname := nil; flabel := nil; occur := blck end;
-
-
- (*compile:*) rewrite(prr); (*comment this out when compiling with pcom *)
- (**********)
- insymbol;
- programme(blockbegsys+statbegsys-[casesy]);
-
- end.
-